[SOLVED] Schrodinger's code (two states happening at the same time?)

luispotro: Allright! In what if loop should I put the value? listMillis is used in the debouncer function.

There's no such thing as an if "loop". If's don't loop, they just check.

Again, follow your code. Put it where it needs to be calculated. Right when the game starts. But definitely not in the middle of the game somewhere so it gets updated constantly while the game is playing.

I think part of what is confusing you is the extra states for early press, good press, and late press. Those are output conditions. Those are things you might tell the player. But they're not really states of the game. The game only really has three states. Waiting to start, started and waiting to trigger, and triggered and waiting for the player to push the button. I think that mixup has your state machine so convoluted that it is hard to follow. Look at the code I posted and see if it isn't a little easier to follow.

arduinodlb: You don't have a permanent offset of 2000. All the calculations are working as expected.

Here's one part of your output

debugtime150
startTime:23101
endTime:20951
Delayval:4000
-1850

and it is correct.

23101 - 20951 - 4000 (the random delay) = -1850, as expected.

So, I don't know what you expect it to do differently??

My average reaction time is around 250 ms. The "game" is suppose to measure the time from where a light turns on until I press a button. -1850 milliseconds means that I pressed the button that time before the light turned on. And that is not correct.A correct value should be aroun 250

Delta_G: I think part of what is confusing you is the extra states for early press, good press, and late press. Those are output conditions. Those are things you might tell the player. But they're not really states of the game. The game only really has three states. Waiting to start, started and waiting to trigger, and triggered and waiting for the player to push the button. I think that mixup has your state machine so convoluted that it is hard to follow. Look at the code I posted and see if it isn't a little easier to follow.

Yeah, that must be the case of my confusion. Also trying to tweak some already made code to serve my purpose. And that I tried to learn everything in just to weeks of starting.

Tomorrow I'll give a look at your code. Thank you!

luispotro: My average reaction time is around 250 ms. The "game" is suppose to measure the time from where a light turns on until I press a button. -1850 milliseconds means that I pressed the button that time before the light turned on. And that is not correct.A correct value should be aroun 250

Ahh. Well that's a different thing entirely.

The problem is you are comparing it to your start and end times. Your start time is set to when the thing is starting, i.e.: before you have pressed the start button. The end time is set to when you press the "start" button. That is when the game starts. So, using endtime - starttime - delaytime makes no sense.

In your original code, I think you want:

elapsedMillis - endTime - delayVal.

You need to time from when state transitions occur. i.e. When the game starts, not the time spent waiting for the start button to be pressed. I would probably rename endTime to startGameTime to help make this more obvious.

Delta_G:
If I were writing a game like this it would go something like this:

#define TIMEOUT 7000ul

enum State {
  STANDBY , LIGHTON, LIGHTOFF};
State state;

const byte buttonPin = 6;
const byte ledPin = 3;
int delayValue;
unsigned long gameStart;
unsigned long reactionStart;
boolean lastButtonCheck = false;
boolean thisButtonCheck = false;

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

pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

state = STANDBY;

Serial.println(“Starting Game”);
}

void loop(){
  // Some edge detection for the button
  boolean b = checkButton();
  if(b != lastButtonCheck){
    lastButtonCheck = b;
    thisButtonCheck = b;
  }
  else {
    thisButtonCheck = false;
  }
   
  switch(state){
  case STANDBY:
    if(thisButtonCheck){
      gameStart = millis();
      delayValue = random(2000, 8000);
      digitalWrite(ledPin, HIGH);  // turn led on
      state = LIGHTON; 
    } 
    break;

case LIGHTON:
    if(thisButtonCheck){
      Serial.println(“You pressed too early”);
      state = STANDBY;
    }
    else if(millis() - gameStart >= delayValue){
      state = LIGHTOFF;
      digitalWrite(ledPin, LOW);  // led off time to react.
      reactionStart = millis();
    }
    break;

case LIGHTOFF:
    if(thisButtonCheck){
      int reactionTime = millis() - reactionStart;
      Serial.print(“You took “);
      Serial.print(reactionTime);
      Serial.println(” milliseconds”);
      state = STANDBY;
    }
    else if(millis() - reactionStart >= TIMEOUT){
      Serial.println(“Timeout”);
      state = STANDBY;
    }
    break;
  }  // switch(state)
}

boolean checkButton(){ 
  static unsigned long lastChange = millis();
  static int lastState = HIGH;
  int currentState = digitalRead(buttonPin);
  if(currentState != lastState){
    lastState = currentState;
    lastChange = millis();
  }
  // 50ms debounce
  if((millis() - lastChange > 50) && currentState == LOW){
    return true;
  }
  return false;
}




You can add the part to setup for two modes.

Which I did. I think we have a winner. I tweaked some things here and there and the code worked as I intended.

Thank you all, especially @arduinodlb and @Delta_G

/* COGNITIVE BIAS TEST 0.3 beta
    Luis Andrés Gonzalez, January 2016
    Adapted from code made by user Delta_G on Arduino Forums http://forum.arduino.cc/index.php?topic=374131.msg2580434#msg2580434
*/


#define TIMEOUT 7000ul

enum State {
  STANDBY , LIGHTON, LIGHTOFF
};
State state;

const char* const modeText[] = {"Random mode", "Fixed time mode"};
enum GameMode {
  RANDOM_TIME,
  FIXED_TIME,
};

GameMode gamemode;

const byte buttonPin  = 6;    // pin where the button will be connected
const byte ledpin1    = 3;    // Left LED
const byte ledPin2    = 8 ;   // Middle LED
const byte ledPin3    = 11;   // Right LED

int delayValue = 1500;
unsigned long gameStart;
unsigned long reactionStart;
boolean lastButtonCheck = false;
boolean thisButtonCheck = false;
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by
bool answered = false;

void setup() {
  // Setup button and LEDs:
  pinMode(buttonPin, INPUT);
  pinMode(ledpin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);

  // Begin serial communication

  Serial.begin(9600);

  Serial.println("Enter Test mode:");
  Serial.println("Press 1 for random mode");
  Serial.println("Press 2 for fixed time mode");

  state = STANDBY;
}

void loop() {
  getTestMode();
  
  if (answered) {
    
    // Some edge detection for the button
    boolean b = checkButton();
    if (b != lastButtonCheck) {
      lastButtonCheck = b;
      thisButtonCheck = b;
    }
    else {
      thisButtonCheck = false;
    }

    switch (state) {
      case STANDBY:
        
        Fade();
        if (thisButtonCheck) {
          gameStart = millis();
          if (gamemode == RANDOM_TIME) {
            delayValue = random(5000, 8000);
          }
          digitalWrite(ledpin1, LOW);  // turn led off
          Serial.println("9090");      // session started
          state = LIGHTOFF;
        }
        break;

      case LIGHTOFF:
        if (thisButtonCheck) {
          Serial.println("1010"); // early pressed code
          state = STANDBY;
        }
        else if (millis() - gameStart >= delayValue) {
          digitalWrite(ledpin1, HIGH);  // led on time to react.
          state = LIGHTON;
          reactionStart = millis();
        }
        break;

      case LIGHTON:
        if (thisButtonCheck) {
          int reactionTime = millis() - reactionStart;
          //Serial.print("You took ");
          Serial.println(reactionTime);
          //Serial.println(" milliseconds");
          state = STANDBY;
        }
        else if (millis() - reactionStart >= TIMEOUT) {
          Serial.println("7777"); // timeout code
          state = STANDBY;
        }
        break;
    }  // switch(state)
  } // if (answered)
} // void loop()

boolean checkButton() {
  static unsigned long lastChange = millis();
  static int lastState = HIGH;
  int currentState = digitalRead(buttonPin);
  if (currentState != lastState) {
    lastState = currentState;
    lastChange = millis();
  }
  // 50ms debounce
  if ((millis() - lastChange > 50) && currentState == LOW) {
    return true;
  }
  return false;
}

void Fade() {

  analogWrite(ledpin1, brightness);

  brightness = brightness + fadeAmount;
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }
  delay(30);
}

int getTestMode() {
  if (!answered) {
    if (Serial.available()) {
      char ch = Serial.read();
      Serial.print("I received: ");
      Serial.println(ch);

      if (ch >= '1' && ch <= '2') {
        if (ch == '1') {
          gamemode = RANDOM_TIME;
        } else {
          gamemode = FIXED_TIME;
        }
        Serial.print("Game mode selected = ");
        Serial.println(modeText[gamemode]);
        answered = true;
      } else {
        Serial.print("Invalid option");
      }
    }
  }
}