I don't understand progression from one "if block" to next on Leonardo.

This is my first attempt at an Arduino sketch. The code below compiles, uploads, and runs, but not as I expected. Leonardo is supposed to wait for a digit (1 or 2) from an E-Prime program, light LED1 or LED2 accordingly, wait for a response on key1 or key2 (pushbuttons), turn off the LED, and compute a reaction time (RT). It does all that, but if either key is pushed BEFORE E-Prime sends the digit, the "if block" waiting for the key push is executed. How does execution get that far? I have placed an alternating LED blink signal loop in that location to let me track progression of execution. At that point, the sketch continues to properly wait for a digit and do its thing, or if a key is pushed it responds to that again! I know I'm missing something pretty basic here. :astonished:

const int LED1 = 11;
const int LED2 = 12;
const int RespKey1 = 2;
const int RespKey2 = 3;
unsigned long NowTime = 0;
unsigned long StartTime = 0;
unsigned long RT = 0;
char ch = '0';

void setup()
{
  Serial.begin(128000); // Initialize serial port to same speed as in E-Prime
  while (!Serial) {     // Wait for serial port to connect. Needed for Leonardo only?
  }
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(RespKey1, INPUT);
  pinMode(RespKey2, INPUT);
}

void loop()
{  
  if(Serial.available() > 0)  // If digit has been sent to Serial device from E-Prime.
  {
    char ch = Serial.read();  // Converts string to an ASCHII character--digit.
    if (ch == '1')
     {
       digitalWrite(LED1, HIGH); 
       unsigned long StartTime = micros();  // records time for later RT  
     }
    else if (ch == '2')
    {    
       digitalWrite(LED2, HIGH); 
       unsigned long StartTime = micros();  // records time for later RT
    }
    else                             // If E-Prime sends anything other than 1 or 2.
    {                                   
      digitalWrite(LED1, HIGH);      // Both LEDs light.  Never happens.
      digitalWrite(LED2, HIGH);
    }
  }                                  // end of if block waiting for digit
  
  if (digitalRead(RespKey1) == 1 || digitalRead(RespKey2) == 1)
  {                                           // If either response key is pushed.
  for(int i = 0; i < 10; i++){          // Alternating LED blinking to show sketch got here.
      digitalWrite(LED1, HIGH);     // Will be taken out later.
      digitalWrite(LED2, LOW);
      delay(50);                          // Sketch gets here when a response key pushed even
      digitalWrite(LED1, LOW);     // when no digit sent by E-Prime beforehand!!
      digitalWrite(LED2, HIGH);
      delay(50);
   }
    unsigned long NowTime = micros();
    digitalWrite(LED1, LOW);        // turn off both LEDs
    digitalWrite(LED2, LOW);
    RT = NowTime - StartTime;
    Serial.println(RT);
  }                                 // end of if block looking for response key push 
}                                   // end of the big "loop"

Any insights would be appreciated.

TimG62

You have two IF statements in your loop():

void loop() {  
  if(Serial.available() > 0)  // If digit has been sent to Serial device from E-Prime.
  {
  }                                  // end of if block waiting for digit
  
  if (digitalRead(RespKey1) == 1 || digitalRead(RespKey2) == 1)
  {                                           // If either response key is pushed.
  }                                 // end of if block looking for response key push 
}                                   // end of the big "loop"

The second IF statement is executed regardless of what the Serial.available() returned. What you probably want to do is keep a flag that indicates that a light has turned on. Then you can use that as part of the second IF to keep the buttons from being processed unless the LED has been turned on. Of course that leaves a cheat: hold down the button until the LED lights up. You can prevent that by detecting when the buttons are pressed early and count that as a FAIL.

TimG62:
This is my first attempt at an Arduino sketch. The code below compiles, uploads, and runs, but not as I expected. Leonardo is supposed to wait for a digit (1 or 2) from an E-Prime program, light LED1 or LED2 accordingly, wait for a response on key1 or key2 (pushbuttons), turn off the LED, and compute a reaction time (RT). It does all that, but if either key is pushed BEFORE E-Prime sends the digit, the "if block" waiting for the key push is executed. How does execution get that far? I have placed an alternating LED blink signal loop in that location to let me track progression of execution. At that point, the sketch continues to properly wait for a digit and do its thing, or if a key is pushed it responds to that again! I know I'm missing something pretty basic here. :astonished:

Try this (untested):

const int LED1 = 11;
const int LED2 = 12;
const int RespKey1 = 2;
const int RespKey2 = 3;
unsigned long NowTime = 0;
unsigned long StartTime = 0;
unsigned long RT = 0;
char ch = '0';
boolean recd = 0; //data received flag

void setup()
{
  Serial.begin(128000); // Initialize serial port to same speed as in E-Prime
  while (!Serial) {     // Wait for serial port to connect. Needed for Leonardo only?
  }
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(RespKey1, INPUT);
  pinMode(RespKey2, INPUT);
}

void loop()
{  
  if(Serial.available() > 0)  // If digit has been sent to Serial device from E-Prime.
  {
    char ch = Serial.read();  // Converts string to an ASCHII character--digit.
    if (ch == '1')
     {
       digitalWrite(LED1, HIGH); 
       StartTime = micros();  // records time for later RT  
   //you've defined StartTime as unsigned long already. No need to do it again.
       recd = 1;  //flag data received
     }
    else if (ch == '2')
    {    
       digitalWrite(LED2, HIGH); 
       StartTime = micros();  // records time for later RT
       //you've defined StartTime as unsigned long already. No need to do it again.
       recd = 1;   //flag data received
    }
    else                             // If E-Prime sends anything other than 1 or 2.
    {                                   
      digitalWrite(LED1, HIGH);      // Both LEDs light.  Never happens.
      digitalWrite(LED2, HIGH);
      recd = 1;  // Don't know if you need this if you've not received anything sensible?  
    }
  }                                  // end of if block waiting for digit
  
  if ((digitalRead(RespKey1) == 1 || digitalRead(RespKey2) == 1) && recd == 1)
    {                                           
     // If either response key is pushed and data received.
  for(int i = 0; i < 10; i++){          // Alternating LED blinking to show sketch got here.
      digitalWrite(LED1, HIGH);     // Will be taken out later.
      digitalWrite(LED2, LOW);
      delay(50);                          // Sketch gets here when a response key pushed even
      digitalWrite(LED1, LOW);     // when no digit sent by E-Prime beforehand!!
      digitalWrite(LED2, HIGH);
      delay(50);
   }
    NowTime = micros();
     //you've defined NowTime as unsigned long already. No need to do it again.
    digitalWrite(LED1, LOW);        // turn off both LEDs
    digitalWrite(LED2, LOW);
    RT = NowTime - StartTime;
    Serial.println(RT);
    recd = 0;  //reset received flag
  }                                 // end of if block looking for response key push 
}                                   // end of the big "loop"

Did you want the button pushed to match the LED lit? Your current code treats both buttons the same.

Okay, I guess that really IS pretty basic. I thought that the first if block, waiting for a digit, would continue to cycle until the digit was received and only then drop down to the block that waits for a key response. But apparently that 2nd if is always just waiting for its own condition so it can execute? I can see how a flag in the second if could prevent that. Would a do-while loop that checks for a key press behave the same way as the 2nd if, or would that be another fix?

Eventually, the particular key that is pushed will be noted and sent to E-Prime for data logging. I simply cut the sketch down to bare bones when I ran into trouble earlier. In fact, the person (subject) who presses the keys will actually be responding to a more complex stimulus that appears on the screen. I simply used the LEDs on the Arduino to be sure that it was responding to the E-Prime program.

Thanks for your help.

An "if" doesn't wait, it just asks a question. If you ask your friend "is it raining?" you get a quick answer, but that doesn't make you wait until the rain stops.

A "while" would be closer, eg.

while (Check_If_It_Is_Raining () )
  Read_A_Book ();