Reaction time to push sensor when LED turned on

Hello,
I'm currently trying to time how long it takes to push a pressure sensor after an LED turns on.

Basically, this is what I want to happen:
LED turns on, millis() takes time reading
Push pressure sensor, millis() takes second time reading, and LED is turned off
Print the time it took to push pressure sensor in the serial monitor

Here is what is actually happening:
LED turns on, if I push the pressure sensor it appears to turn off, the serial monitor prints the time as 0 seconds.
If I don't push the pressure sensor, and let the LED keep running and blinking off and on, the serial monitor prints the time decreasing by 2 seconds every time it prints.

Does anyone know why this is happening? I've been trying to figure this out for a long time, and I'm kind of lost as to why it's not working properly.

Example run from serial monitor:

Your time:
5919
Your time:
0
Your time:
0
Your time:
5913
Your time:
5911
Your time:
5909

Here is my code:

//Take time reading, turn led on
//If pressure is felt
//Take time reading
//Turn led off



int sensePin = 2;
int ledPin = 9;

void setup()
{

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}
  void loop()
  {
    unsigned long time1;
    unsigned long time2;
    unsigned long time3;
    int pressure;
       
    digitalWrite(ledPin,HIGH); 
    time1 = millis(); 
    //Turn LED on, take time reading when it turns on
    
    pressure = analogRead(sensePin);
  
    if (pressure >= 25)  //if pressure is felt
    {
      digitalWrite(ledPin,LOW);
      time2 = millis();   
      //turn LED off and take second time reading
    }
    
          
     time3 = (time2 - time1)/1000;
    //Duration in seconds from when led turned on, and pressure was felt
      Serial.println("Your time: ");
      Serial.println(time3);
      delay(2000);
  }

This is actually quite simple. Turn an LED on at a random interval and record the time when the LED is on. You could also set a ON flag. Now look for the button to be pressed. Once pressed, find the time difference and turn LED off.

I haven't looked at your code yet.

Using local variables, unless they are static, is NOT going to work. They are reallocated each time loop() is called. They are NOT initialized. The analogRead() and if statement do not block, waiting for a non-zero reading.

So, the results you get are exactly what I'd expect.

Try:

//Take time reading, turn led on
//If pressure is felt
//Take time reading
//Turn led off


unsigned long time1;
unsigned long time2;
unsigned long time3;
int pressure;
int sensePin = 2;
int ledPin = 9;

void setup()
{

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}
void loop()
{

  if (digitalRead(ledPin) == LOW)
  {
    digitalWrite(ledPin, HIGH);
    time1 = millis();
    //Turn LED on, take time reading when it turns on
  }

  pressure = analogRead(sensePin);

  if (pressure >= 25)  //if pressure is felt
  {
    digitalWrite(ledPin, LOW);
    time2 = millis();
    //turn LED off and take second time reading

    time3 = (time2 - time1);
    //Duration in seconds from when led turned on, and pressure was felt
    Serial.println("Your time in milliseconds is: ");
    Serial.println(time3);
    delay(2000);
  }
}

Why did I move these so they would be global?
unsigned long time1;
unsigned long time2;
unsigned long time3;

Why did I add?
if (digitalRead(ledPin) == LOW)
{
. . .
}

Why did I move this into the last "if" area?
time3 = (time2 - time1);
//Duration in seconds from when led turned on, and pressure was felt
Serial.println("Your time in milliseconds is: ");
Serial.println(time3);
delay(2000);

Why did I remove /1000?
time3 = (time2 - time1);

For some reason the LED is not turning on at all with the new code.

Why did I move these so they would be global?

I'm not sure, but I guess you need the entire program to be able to access the variables? I'm not used to writing arduino code, most of the small programs I've written in c++ I've only had to declare the variables within each function.

Why did I add?
if (digitalRead(ledPin) == LOW)

In the original code I wrote, it started with the LED on, this way it starts with the LED off, then turns it on. Again, I'm not totally sure why, maybe if I want to take a time difference I have to start with the LED off?

Why did I move this into the last "if" area?

It's only supposed to print a time reading if you actually push the sensor, in my case it was just printing the delay time difference if I didn't push the sensor.

Why did I remove /1000?

In this way it prints in milliseconds, but why can't I divide by 1000 to make it print in seconds? Does the integer 1000 cause the rest to be changed to an int?

Make sure you have the LED wired correctly.
Note
ledPin should be 9
I think my fist posting had 13 but I changed it back to 9 right away .

That was indeed the problem, it works now. Thanks so much!
So why did it need the additional if statement that you added? Because I'd like to understand how it works rather than just copying your code.

Why did I move these so they would be global?
I'm not sure, but I guess you need the entire program to be able to access the variables? I'm not used to writing arduino code, most of the small programs I've written in c++ I've only had to declare the variables within each function.

As PaulS said, "They are reallocated each time loop() is called."
You don't what them to.

Remove the additions one at time.
Try to run the code without that change, then report back what happens for each case.

Mine

  if (digitalRead(ledPin) == LOW)
  {
    digitalWrite(ledPin, HIGH);
    time1 = millis();
    //Turn LED on, take time reading when it turns on
  }

Yours

    digitalWrite(ledPin,HIGH); 
    time1 = millis(); 
    //Turn LED on, take time reading when it turns on
    
    pressure = analogRead(sensePin);

If you use "Yours", time1 will get reinitialized each time through loop()
This is very fast, micro seconds for example.
You don't want to do this as time1 is supposed to be the time the LED went on.

Mine only updates time1 once, when the LED is OFF.

Try:
time3 = (time2 - time1) /1000;

Then try:
time3 = (time2 - time1);

What is the difference?

Try this:

//Take time reading, turn led on
//If pressure is felt
//Take time reading
//Turn led off

unsigned long time1;
unsigned long time2;
unsigned long time3;
int pressure;
int sensePin = 2;
int ledPin = 9;

void setup()
{

  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}
void loop()
{

  if (digitalRead(ledPin) == LOW)
  {
    digitalWrite(ledPin, HIGH);
    time1 = millis();
    //Turn LED on, take time reading when it turns on
  }

  pressure = analogRead(sensePin);

  if (pressure >= 25)  //if pressure is felt
  {
    digitalWrite(ledPin, LOW);
    time2 = millis();
    //turn LED off and take second time reading

    unsigned long x = (time2 - time1)%1000;
    time3 = (time2 - time1)/1000;
    //Duration in seconds from when led turned on, and pressure was felt
    Serial.println("Your time is: ");
    Serial.print(time3);
    Serial.print(".");
    Serial.print(x);
    Serial.println(" seconds.");
    delay(2000);
  }
}

What is happening here?
unsigned long x = (time2 - time1)%1000;

If you are thinking of using this reaction test in part of a bigger ( like slow sketch with loads of SerialPrints and delays etc ) you might look into simply having your pushbutton between pin2 and ground, and assign an interrupt routine to record time 2 when the interrupt signal falls. .

Look it up, its quite simple. ( set pin 2 as pullup )

Although if you are only measuring seconds you might not worry about the accuracy :slight_smile: