Game Reaction tester and two capacitive sensors

Hi.

Based on this .. Arduino Reaction Timer with LCD Display | derekmolloy.ie
I'm trying to count two different times based on two capacitive sensors.

As you can see in my test code

  1. When StartSwitch pressed and BaseSensor is 1 the code waiting for a random amount of time and then RedLight goes ON
  2. Then i'm counting the time in millis between LED ON and Release BaseState and later displaying it in my LCD.

What i also want to count ...unsuccesfully so far .. is the time between the BaseState released and the EndState=1 and then display it to my LCD.

Can please someone help me ?

Thank you in advance

/*
 Arduino Reaction Timer using an RGB LCD 16x2 Character Display
   Derek Molloy, DCU, Ireland.
   Using LCD library from: 
   http://www.arduino.cc/en/Tutorial/LiquidCrystal 
*/
#include <CapacitiveSensor.h>
#include <LiquidCrystal.h>  // include LCD library

// Set up the display with 4 bits - R/W tied to GND
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // RS, E, D4-D7

int RedLight         =  6;    // red stop LED
int BlueLight         =  10;    // red stop LED
int StartSwitch      =  1;    // reaction timer button
//int BaseSwitch      =  9;    // reaction timer button
//int EndSwitch      =  7;    // reaction timer button

const int PotBase = A0;       // analog IN Sensitinity Base
int PotBaseVal = 0;           // variable to store the value read from PotBase A3
int BaseSense = 0;            // value to adjust Base sensitivity
int BaseState = 0;           //this variable controls if BaseSensor is ON=1 or OFF=0
CapacitiveSensor   BaseSensor = CapacitiveSensor(7,8);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

const int PotEnd = A1;       // analog IN Sensitinity End
int PotEndVal = 0;           // variable to store the value read from PotEnd A1
int EndSense = 0;            // value to adjust End sensitivity
int EndState = 0;           //this variable controls if EndSensor is ON=1 or OFF=0
CapacitiveSensor   EndSensor = CapacitiveSensor(7,9);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

// States of execution
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
//int buttonState1 = 0;         // current state of the button
//int lastButtonState1 = 0;     // previous state of the button
long randomDelayTime;        // holds the random time amount
boolean prepareState = true; // in introduction mode
boolean isTiming = false;    // timing the press state
long timerStartMillis;       // the time when the timer started
long timerMidMillis;         // the time when in Mid state
long timerEndMillis;         // the time when the timer finished
long difference2;



// Setup function - called only once
void setup() {
  pinMode(RedLight, OUTPUT);       // red LED is an output
  pinMode(BlueLight, OUTPUT);       // Blue LED is an output
  
   BaseSensor.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
   EndSensor.set_CS_AutocaL_Millis(0xFFFFFFFF);
  
 // pinMode(StartSwitch, INPUT);     // button is an input
 // pinMode(BaseSwitch, INPUT);     // button is an input
  
  lcd.begin(16, 2);              // 16 Columns by 2 Rows
  randomSeed(analogRead(2));     // use unconnected pin to seed random sequence
}

void loop() {
  
    PotBaseVal = analogRead(PotBase);    // read the input pin  
    BaseSense = map(PotBaseVal, 0, 1023, 0, 62);
    long start = millis();
    long total1 =  BaseSensor.capacitiveSensor(10);
    long total2 =  EndSensor.capacitiveSensor(10);
    //long total3 =  cs_4_8.capacitiveSensor(30);
    
     if (total1 > 20){ BaseState =1; } else { BaseState =0; }
     
     if (total2 > 20){ EndState =1; } else { EndState =0; }
  
  
  buttonState = digitalRead(StartSwitch);
 // buttonState1 = digitalRead(EndSwitch);
  
  if(prepareState)
  {                // prepare state - give out the instruction to press button
    lcd.setCursor(0,0);            // set cursor to 0,0 (top left)  
    lcd.print("Reaction Tester:"); // string on the top row
    lcd.setCursor(0,1);            // next row
    lcd.print(" [Press Button] "); // string on the next row
    
    //============================================================= TEST BASE & End =====================================================
    
    if(BaseState == 1) {digitalWrite(RedLight, HIGH);} else { digitalWrite(RedLight, LOW); }
    
    if(EndState == 1) {digitalWrite(BlueLight, HIGH);} else { digitalWrite(BlueLight, LOW); }
     //============================================================= TEST BASE & End =====================================================
   
    
    if (BaseState ==1 && buttonState != lastButtonState)  // if the button is pressed
    {
      digitalWrite(RedLight, LOW);
      lcd.clear();                 // clear the display
      lcd.setCursor(0,0);
      lcd.print("---- Ready -----");
      randomDelayTime = random(10000);  // this is the random amount to be used 0-10 seconds
      while (BaseState !=1 ) {} // wait until the button is released
      prepareState = false;       // finished prepare state - lets move on
    }
  }
  else // not in prepare state
  {
     if (!isTiming)                // the timer isn't running, so we are pausing for random amount
     {
        delay(randomDelayTime);      // delay for the random amount
        digitalWrite(RedLight, HIGH);  // when finished - set red LED high
       
        lcd.setCursor(0,0);          // press now message
        lcd.print("------ GO ------"); 
        isTiming = true;             // now we are ready to start timing reactions
        timerStartMillis = millis(); // get the current time 
     }
     else // now we are timing person's reaction
     {
        if (BaseState == 0)  // when they release the button
        {
           timerMidMillis = millis(); // get the current time
           digitalWrite(RedLight, LOW); // turn off the red led
           long difference = timerMidMillis - timerStartMillis; // time taken is difference between times
           lcd.clear();                    // clear the LCD
           lcd.setCursor(0,0);
           
           if (difference < 10 )            // If the difference is 0 they held the button - or are supermen!
           {
               lcd.print("--- Too Soon ---");
               digitalWrite(RedLight, HIGH); // turn off the red led
               delay(200);
               digitalWrite(RedLight, LOW); // turn off the red led
               delay(200);
               digitalWrite(RedLight, HIGH); // turn off the red led
               delay(200);
               digitalWrite(RedLight, LOW); // turn off the red led
               delay(200);
               digitalWrite(RedLight, HIGH); // turn off the red led
               delay(200);
               digitalWrite(RedLight, LOW); // turn off the red led
           }
           else  // valid time
           {  
              
             lcd.setCursor(0,0);
             lcd.print("ReacTime : ");
             lcd.print(difference);
             lcd.setCursor(0,1);
             lcd.print("GameTime : ");
             lcd.print(difference2);              // milliseconds
             
             while (EndState ==1)  // when they hit end button
              {
             
                timerEndMillis = millis(); // get the current time  
                difference2 = timerEndMillis - timerMidMillis; // time taken is difference between times
                //lcd.clear();   
                //lcd.setCursor(0,0);
                //lcd.print("ReacTime : ");
                //lcd.print(difference);
                lcd.setCursor(0,1);
                lcd.print("GameTime : ");
                lcd.print(difference2);     
              }
           
           }
           delay(5000);                    // leave the message on the screen for 5 seconds
           isTiming = false;               // ready to start timing again
           prepareState = true;            // ready to start all over
           //setDisplayRGB(255,255,255);     // set the LCD backlight to white
        }
     }
  }
}
1) When StartSwitch pressed and BaseSensor is 1

BaseSensor is an instance of CapacitiveSensor. The instance will NEVER be 1. Try again.

What do you mean ?

if (total1 > 20){ BaseState =1; } else { BaseState =0; }

What do you mean ?

BaseState != BaseSensor

quote author=PaulS link=topic=208757.msg1534510#msg1534510 date=1388967061]

What do you mean ?

BaseState != BaseSensor
[/quote]

What i'm trying to do is to use readings from

CapacitiveSensor   BaseSensor = CapacitiveSensor(7,8);
CapacitiveSensor   EndSensor = CapacitiveSensor(7,9);

and use them as simple ON-OFF switch

long total1 =  BaseSensor.capacitiveSensor(10);
long total2 =  EndSensor.capacitiveSensor(10);
    ............ ....... ........    
if (total1 > 20){ BaseState =1; } else { BaseState =0; }
if (total2 > 20){ EndState =1; } else { EndState =0; }

and seems that is working fine ...except in last part when BaseState == 0 ( switch OFF )
till EndState == 1 ( when EndSwitch ==1 )
where i can't display the last time reading
I guess that the problem is here

else  // valid time
           {  
              
             lcd.setCursor(0,0);
             lcd.print("ReacTime : ");
             lcd.print(difference);
             lcd.setCursor(0,1);
             lcd.print("GameTime : ");
             lcd.print(difference2);              // milliseconds
             
             while (EndState ==1)  // when they hit end button
              {
             
                timerEndMillis = millis(); // get the current time  
                difference2 = timerEndMillis - timerMidMillis; // time taken is difference between times
                //lcd.clear();   
                //lcd.setCursor(0,0);
                //lcd.print("ReacTime : ");
                //lcd.print(difference);
                lcd.setCursor(0,1);
                lcd.print("GameTime : ");
                lcd.print(difference2);     
              }
           
           }

in the last while (EndState ==1)

Right ?

Please give me a hand on this
Thank you.

             while (EndState ==1)  // when they hit end button
              {
             
                timerEndMillis = millis(); // get the current time  
                difference2 = timerEndMillis - timerMidMillis; // time taken is difference between times
                //lcd.clear();   
                //lcd.setCursor(0,0);
                //lcd.print("ReacTime : ");
                //lcd.print(difference);
                lcd.setCursor(0,1);
                lcd.print("GameTime : ");
                lcd.print(difference2);     
              }

Once this block starts, there is nothing to cause it to end. Is that what you really want?

except in last part when BaseState == 0 till EndState == 1

You are confusing events (BaseState becomes 0, EndState becomes 1, etc.) and times (until some time).

Please give me a hand on this

I would, but I really have no idea what you are trying to do.

Before we go there, though, have you determined how long it takes to read a capacative sensor? Do you think such sensors make sense as reaction timers?

PaulS:

Please give me a hand on this

I would, but I really have no idea what you are trying to do.

Thank you Paul for your help

I need to find a way to count how much time it takes for the user to press EndSensor (EndState==1) from the time that he releases the BaseSensor(BaseState==0) and then display this time in the second row of the LCD

PaulS:
Before we go there, though, have you determined how long it takes to read a capacative sensor? Do you think such sensors make sense as reaction timers?

To be honest i think that this kind of sensors are not accurate enough but at the current time it's what i have handy for use. :(.
On the other hand i belive that i can calculate and substract the time takes the sensor to respond.
According to this example in the Capacitive Library .. Arduino Playground - HomePage

void loop()                    
{
    long start = millis();
    long total1 =  cs_4_2.capacitiveSensor(30);
    long total2 =  cs_4_5.capacitiveSensor(30);
    long total3 =  cs_4_8.capacitiveSensor(30);

    Serial.print(millis() - start);        // check on performance in milliseconds
    Serial.print("\t");                    // tab character for debug window spacing

    Serial.print(total1);                  // print sensor output 1
    Serial.print("\t");
    Serial.print(total2);                  // print sensor output 2
    Serial.print("\t");
    Serial.println(total3);                // print sensor output 3

    delay(10);                             // arbitrary delay to limit data to serial port 
}

i think that ........ Serial.print(millis() - start); // check on performance in milliseconds
can be substracted from the"reaction" time in order to get a more accurate result.
What do you think ?

i think that ........ Serial.print(millis() - start); // check on performance in milliseconds
can be substracted from the"reaction" time in order to get a more accurate result.
What do you think ?

You can't subtract Serial.print() anything from the time. That would be a bit like subtracting elephants from peanut butter.

You can subtract the time it takes to read the two sensors from some time, but that might not be necessary, unless you consistently read both sensors.

In any case, you need to use millis() to record when one sensor's value exceeds some threshold (at which time you'd provide some cue that timing has started (like lighting an LED)). Then, use millis() to record when the other sensor exceeds some (possibly different) threshold. The time between the two events (possibly adjusted to remove the sensor read time) is the reaction time.

PaulS:
You can't subtract Serial.print() anything from the time. That would be a bit like subtracting elephants from peanut butter.

Hehe..
i was trying to point to you the line of the code where calculation takes place. :wink:
millis() - start

PaulS:
You can subtract the time it takes to read the two sensors from some time, but that might not be necessary, unless you consistently read both sensors.

In any case, you need to use millis() to record when one sensor's value exceeds some threshold (at which time you'd provide some cue that timing has started (like lighting an LED)). Then, use millis() to record when the other sensor exceeds some (possibly different) threshold. The time between the two events (possibly adjusted to remove the sensor read time) is the reaction time.

This is in my next step..
For now i can't find what i'm doing wrong and i can't display the delay2 in my LCD. :blush:
Can you please help me on that ?

For now i can't find what i'm doing wrong and i can't display the delay2 in my LCD.

We're not getting anywhere when you use names that are not in your code.

PaulS:

For now i can't find what i'm doing wrong and i can't display the delay2 in my LCD.

We're not getting anywhere when you use names that are not in your code.

Oups....my mistake..sorry :blush:

i mean .... difference2

i mean .... difference2

You should consider unplugging the LCD and putting it away. Concentrate on getting the logic of the program correct. Use Serial.print() statements to track where in the code you are. When the program flow is correct, then you can add the LCD back in and print data to it.

Your code is unnecessarily complex. You have several states - timing not started, timing in progress, timing done. There is a limited amount of work to do in each state, and only one way to get from one state to another.

PaulS:
You should consider unplugging the LCD and putting it away. Concentrate on getting the logic of the program correct. Use Serial.print() statements to track where in the code you are.

Done

PaulS:
When the program flow is correct, then you can add the LCD back in and print data to it.

The code flows correctly untill the last state where i want to count the difference2 time (starting at BaseState == 0 untill EndState==1).
Whatever i try EndState NEVER goes to 1.
What i m doing wrong ?

PaulS:
Your code is unnecessarily complex. You have several states - timing not started, timing in progress, timing done. There is a limited amount of work to do in each state, and only one way to get from one state to another.

I know...but is the best i can do :blush:

/*
 Arduino Reaction Timer using an RGB LCD 16x2 Character Display
   Derek Molloy, DCU, Ireland.
   Using LCD library from: 
   http://www.arduino.cc/en/Tutorial/LiquidCrystal 
*/
#include <CapacitiveSensor.h>
#include <LiquidCrystal.h>  // include LCD library

// Set up the display with 4 bits - R/W tied to GND
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // RS, E, D4-D7

int RedLight         =  6;    // red stop LED
int BlueLight         =  10;    // red stop LED
int StartSwitch      =  1;    // reaction timer button

const int PotBase = A0;       // analog IN Sensitinity Base
int PotBaseVal = 0;           // variable to store the value read from PotBase A3
int BaseSense = 0;            // value to adjust Base sensitivity
int BaseState = 0;           //this variable controls if BaseSensor is ON=1 or OFF=0
CapacitiveSensor   BaseSensor = CapacitiveSensor(7,8);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

const int PotEnd = A1;       // analog IN Sensitinity End
int PotEndVal = 0;           // variable to store the value read from PotEnd A1
int EndSense = 0;            // value to adjust End sensitivity
int EndState = 0;           //this variable controls if EndSensor is ON=1 or OFF=0
CapacitiveSensor   EndSensor = CapacitiveSensor(7,9);        // 10 megohm resistor between pins 4 & 2, pin 2 is sensor pin, add wire, foil

// States of execution
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
long randomDelayTime;        // holds the random time amount
boolean prepareState = true; // in introduction mode
boolean isTiming = false;    // timing the press state
long timerStartMillis;       // the time when the timer started
long timerMidMillis;         // the time when in Mid state
long timerEndMillis;         // the time when the timer finished
long difference2;
long difference;


// Setup function - called only once
void setup() {
  pinMode(RedLight, OUTPUT);       // red LED is an output
  pinMode(BlueLight, OUTPUT);       // Blue LED is an output
  
   BaseSensor.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
   EndSensor.set_CS_AutocaL_Millis(0xFFFFFFFF);
 
  randomSeed(analogRead(2));     // use unconnected pin to seed random sequence
  Serial.begin(9600);
}

void loop() 
{  
    long start = millis();
    long total1 =  BaseSensor.capacitiveSensor(10);
    long total2 =  EndSensor.capacitiveSensor(10);
    buttonState = digitalRead(StartSwitch);
        
    if (total1 > 20){ BaseState =1; } else { BaseState =0; }
    if (total2 > 20){ EndState =1; } else { EndState =0; }
  
    if(prepareState)// prepare state - give out the instruction to press button
    {                
      Serial.println("  Prepare State  ");
       
      if (BaseState ==1 && buttonState != lastButtonState)  // if the button is pressed
      {
        digitalWrite(RedLight, LOW);
        Serial.println("  READY  ");
        randomDelayTime = random(10000);  // this is the random amount to be used 0-10 seconds
        while (BaseState !=1 ) {} // wait until the button is released
        prepareState = false;       // finished prepare state - lets move on
      }
    }
    else // not in prepare state
    {
       if (!isTiming)                // the timer isn't running, so we are pausing for random amount
       {
          delay(randomDelayTime);      // delay for the random amount
          digitalWrite(RedLight, HIGH);  // when finished - set red LED high
          Serial.println("  --- GO ---  ");
          isTiming = true;             // now we are ready to start timing reactions
          timerStartMillis = millis(); // get the current time 
       }
       else // now we are timing person's reaction
       {
          if (BaseState == 0 && EndState==0)  // when they release the button
          {
             timerMidMillis = millis(); // get the current time
             difference = timerMidMillis - timerStartMillis; // time taken is difference between times            
             digitalWrite(RedLight, LOW); // turn off the red led
                                    
             if (difference < 10 )            // If the difference is 0 they held the button - or are supermen!
             {
                 Serial.println("  -- TOO SOON --  ");
             }
             else
             {
                  Serial.print("Reaction Time : ");
                  Serial.print(difference);
                  
                 if (EndState ==1)  // when they hit end button
                 {  
                     timerEndMillis = millis(); // get the current time  
                     difference2 = timerEndMillis - timerMidMillis; // time taken is difference between times
                                 
                     Serial.println("  EndSensor PRESSED  ");
                 }   
             }
              delay(5000);                    // leave the message on the screen for 5 seconds
              isTiming = false;               // ready to start timing again
              prepareState = true;            // ready to start all over       
          }
       } 
    }
}
        while (BaseState !=1 ) {} // wait until the button is released

This will never end, if it starts, since nothing in the (empty) body ever changes BaseState.

Of course, the while loop will never be executed, since it is in a block that only executes if BaseState IS 1.

What does difference2 track? How is that different from what difference tracks?

PaulS:

        while (BaseState !=1 ) {} // wait until the button is released

This will never end, if it starts, since nothing in the (empty) body ever changes BaseState.

Of course, the while loop will never be executed, since it is in a block that only executes if BaseState IS 1.

Hmmm..i guess this a remaining part of code during several modifications :blush:

PaulS:
What does difference2 track? How is that different from what difference tracks?

difference is tracking the time in millis starting right after RedLight goes on untill the time that the player releases the baseswitch BaseState == 0 ..actually i'm counting his reaction time

difference2 i want to track the time starting at BaseState ==0 untill EndState ==1. when he finifhes the game

Sorry for my poor English ...i'll try to explain better in the below "diagram"

RedLight -------------------------------------- BaseState==0 ---------------------------------EndState==1
Light goes on ---------------------------- Player releases BaseState --------------------- player completes the game
timerStartMillis = millis();------------------- timerMidMillis = millis(); ----------------------timerEndMillis = millis();
<--difference = timerMidMillis - timerStartMillis;---->> <<<------difference2 = timerEndMillis - timerMidMillis; -->>

I hope it's more clear now
Once again thank you for your time ...

Hi Paul...
Seems that the last days i took several lessons but no one of them lead me to the right results.. :blush: =(
I really need your help.