Cant stop code from being run after reset

MaJiG:
Your new initialization code:

byte lastbuttonState = 0; // new global variable

initializes to the button being pressed in the new scheme, yes?

Please post your entire code...

My code? It's just a snippet from his code that I made. Just replace his loop function with one of mine.

No, I meant Webca.

I didnt get it to work :frowning:

Here is my code:

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
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

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.

}

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

  if(buttonState1 == buttonState2) {
    if(buttonState2 != lastButtonState) {
     activate();
     lastButtonState = buttonState2;
    }
  }

    

}


void activate()
{
      
    buttonState = digitalRead(buttonPin);                   // read the button state and store

    if (buttonState == HIGH){     
       // if true then found a new button press while clock is not running - start the clock

       startTime = millis();                                   // store the start time
       delay(5);                                               // short delay to debounce switch
       lastButtonState = buttonState;                          // store buttonState in lastButtonState, to compare next time

    }

    else if (buttonState == LOW){     
       // if true then found a new button press while clock is running - stop the clock and report

         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 / 1000L));         // divide by 1000 to convert to seconds - then cast to an int to print

         lcd.print(".");                             


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


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

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

    }

    else{
       lastButtonState = buttonState;                         // store buttonState in lastButtonState, to compare next time
    }


}

Try using a global boolean variable to keep track of whether the clock is running. Check for a button press. When you detect one, check for whether the clock is running. If it is, show the elapsed time, otherwise note millis. In both cases, set the boolean appropriately for the new situation. You should be able to make the whole thing much simpler this way.

What exactly should it be showing? With your code as of now, when the button is pressed, you see the change in time. However when I took out the " ; " in this line "elapsedTime = millis(); - startTime;" and when I just press the button, I get a readout of between 0.064 - 0.083. BUT, if I hold the button, the counter continues to accumulate and I get +3.250 when held for 3 seconds.

Which one is correct?

Added: change the println to just print for the last line, println(fractional) => print(fractional).
println gives you junk on the end.

PeterH:

Webca:
I want the sketch to stop and wait for a button press.

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.

But that would work and it's -much- too simple.

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.