Capture the point for children

So I am creating a capture the point type game for my children and their friends.

How and what:

  • When you first push the button it takes 5 seconds to capture the point. Red momentary switch needs to be pushed for 5 seconds then a red LED comes on
  • Now a child from a blue team comes to capture that same point and she/he needs to hold for 11 seconds. 5 seconds to remove the red LED, 1 second to go into neutral and 5 seconds to take the blue led
  • Now I have done the part for 11 seconds, that works, but when a child let's go of a button after let's say 6 seconds it should go to neutral, then if he/she starts to push again it should take only 5 seconds to take the point

The code is simple, I have millis to track the time, then I watch how many seconds have passed( I use IF, ELSE IF).
My question is how and what should use to divert if the child lets go of a button in the mark between neutral and let say red. The child starts to push the button again, it should only count to 5 seconds then turn red.

Always show us your current compete sketch.
Use CTRL T to format the sketch.
Please use code tags.
Use the </> icon in the posting menu.

[code] Paste sketch here. [/code]

.

cro_dude:
The code is simple,

Perhaps. But we can't see it.

Post your program. And please use the code button </>

so it looks like this

. See How to use the Forum

...R

Sorry for not putting the code up, a lot of things where in my language :).

This part is for buttons,leds etc.. .It has some redudant lines

//Buttons
int send_R = 12;
int send_B = 11;

//rgb LED
int led1R = 10;
int led1B = 9;
int led2R = 8;
int led2B = 7;


int previusR = LOW;
int previousB = LOW;
int neutral = LOW;
long debounce = 200;
long dur_on = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
int state = LOW;
int stateB = LOW;
int stateR = LOW;
unsigned long interval = 4;
unsigned long interval2 = 2;
unsigned long interval3 = 5;
unsigned long interval4 = 9;
long time = 0;

void setup() {
  pinMode(send_R, INPUT);
  pinMode(send_B, INPUT);
  pinMode(led1R, OUTPUT);
  pinMode(led1B, OUTPUT);
  pinMode(led2R, OUTPUT);
  pinMode(led2B, OUTPUT);
  Serial.begin(9600);
}

Void loop

void loop() {
  unsigned long currentMillis = millis();
  int buttonR = digitalRead(send_R);
  int buttonB = digitalRead(send_B);

  dur_on = (millis() - time) / 1000;

  if (buttonR == HIGH && previusR == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }

  if (buttonB == HIGH && previousB == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }

So these part of the code is the deal breaker.
It goes like this:

  • first, you need to hold the red button for 5-second or more. The red led goes on.
  • then you need to hold the blue button for 5-seconds or more. Then the red light dies and the blue light lights up
  • Now if you push the red button again the blue light flickers, dies then after 10 seconds it goes to re.
  // using this to so that if the blue button was pressed after the red one it uses this IF for the red button, so that it takes you from blue to neutral to red
  if ((buttonR == HIGH) && (millis() - time > debounce))
  {
    if ((stateB == LOW) && (dur_on >= interval)) {

      digitalWrite(led2R, HIGH);
      digitalWrite(led2B, LOW);
      Serial.println("first led is on");
      state == HIGH;
    }

    if ((stateB == HIGH) && (neutral == LOW)) {
      if (dur_on <= interval) {
        digitalWrite(led2B, HIGH);
        delay(interval2);
        digitalWrite(led2B, LOW);
        Serial.println("losing blue led");
      }

      else if ((dur_on >= 5) && (dur_on <= 6)) {
        digitalWrite(led2R, LOW);
        digitalWrite(led2B, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("Neutral");
      }

      else if (dur_on >= interval4) {
        digitalWrite(led2R, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("red led on");
      }
    }
  }

This code is for the blue LED on if it meets the 5-second interval

  if ((buttonB == HIGH) && (millis() - time > debounce))
  {
    if (dur_on >= interval) {
      previousMillis2 = dur_on;
      digitalWrite(led2B, HIGH);
      digitalWrite(led2R, LOW);
      stateB = HIGH;
      stateR = HIGH;
      Serial.println("Blue is on");
    }
  }

  previusR = buttonR;
  previousB = buttonB;

}

Please post the code as a single piece so I don't have to worry about errors creeping in when I join the parts.

...R

//Buttons
int send_R = 12;
int send_B = 11;

//rgb LED
int led1R = 10;
int led1B = 9;
int led2R = 8;
int led2B = 7;


int previusR = LOW;
int previousB = LOW;
int neutral = LOW;
long debounce = 200;
long dur_on = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
int state = LOW;
int stateB = LOW;
int stateR = LOW;
unsigned long interval = 4;
unsigned long interval2 = 2;
unsigned long interval3 = 5;
unsigned long interval4 = 9;
long time = 0;

void setup() {
  pinMode(send_R, INPUT);
  pinMode(send_B, INPUT);
  pinMode(led1R, OUTPUT);
  pinMode(led1B, OUTPUT);
  pinMode(led2R, OUTPUT);
  pinMode(led2B, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();
  int buttonR = digitalRead(send_R);
  int buttonB = digitalRead(send_B);

  dur_on = (millis() - time) / 1000;

  if (buttonR == HIGH && previusR == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }

  if (buttonB == HIGH && previousB == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }


  // using this to so that if the blue button was pressed after the red one it uses this IF for the red button, so that it takes you from blue to neutral to red
  if ((buttonR == HIGH) && (millis() - time > debounce))
  {
    if ((stateB == LOW) && (dur_on >= interval)) {

      digitalWrite(led2R, HIGH);
      digitalWrite(led2B, LOW);
      Serial.println("first led is on");
      state == HIGH;
    }

    if ((stateB == HIGH) && (neutral == LOW)) {
      if (dur_on <= interval) {
        digitalWrite(led2B, HIGH);
        delay(interval2);
        digitalWrite(led2B, LOW);
        delay(interval2);
        digitalWrite(led2B, HIGH);
         delay(interval2);
         digitalWrite(led2B, LOW);
        Serial.println("losing blue led");
      }

      else if ((dur_on >= 5) && (dur_on <= 6)) {
        digitalWrite(led2R, LOW);
        digitalWrite(led2B, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("Neutral");
      }

      else if (dur_on >= interval4) {
        digitalWrite(led2R, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("red led on");
      }
    }
  }


  if ((buttonB == HIGH) && (millis() - time > debounce))
  {
    if (dur_on >= interval) {
      previousMillis2 = dur_on;
      digitalWrite(led2B, HIGH);
      digitalWrite(led2R, LOW);
      stateB = HIGH;
      stateR = HIGH;
      Serial.println("Blue is on");
    }
  }

  previusR = buttonR;
  previousB = buttonB;

}

I don't think it will be easy (maybe not possible) to get your code to work in that way.

It will be much simpler if you use a "state machine" concept - which is a rather grand way of saying that you should use variables to keep track of what is happening.

I think your project has a series of states something like this

  • waiting for a button press
  • buttonA being held
  • buttonA held long enough
  • waiting for a button press
  • buttonB being held
  • buttonB held long enough

but when I write them down like that I suspect I don't really understand what you are trying to do.

Separately from that (while still consistent with it) this code is very unwieldy and repetitive

 if (buttonR == HIGH && previusR == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }

  if (buttonB == HIGH && previousB == LOW && millis() - time > debounce)
  {
    time = millis();
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
  }

For a start, both tests give the same result so it is hard to see the purpose of the tests

Then, both tests depend on the same time so it would make sense to deal with that first

if ( millis() - time > debounce ) {
    if (buttonR == HIGH && previusR == LOW) {

    }
    if (buttonB == HIGH && previousB == LOW) {

    }
}

...R

So the main part that I am trying to work out is how to is this.

  • When you push the red or the blue button it takes 5 seconds to hold it and the same color LED will come ON. So you have two buttons red and blue and 2 RGB LEDs.
  • Now let's say the first captured color is red. The next child that comes goes to capture the blue light,
    He or she needs to hold the blue button for longer because he/she need to take the red light first(5-seconds), then after that there is a neutral time of 1-2 seconds where the light goes off then if he/or she holds it for longer than additional five seconds the blue light will come on(so in total 11 seconds needs to hold to go from red to neutral to blue)
  • The issue that I got is what kind of code to use when a child lets go of the button in the neutral or before the additional 5 seconds mark. The currently in the code it starts again from blinking blue to neutral to red
// using this to so that if the blue button was pressed after the red one it uses this IF for the red 
button, so that it takes you from blue to neutral to red
  if ((buttonR == HIGH) && (millis() - time > debounce))
  {
    if ((stateB == LOW) && (dur_on >= interval)) {

      digitalWrite(led2R, HIGH);
      digitalWrite(led2B, LOW);
      Serial.println("first led is on");
      state == HIGH;
    }

    if ((stateB == HIGH) && (neutral == LOW)) {
      if (dur_on <= interval) {
        digitalWrite(led2B, HIGH);
        delay(interval2);
        digitalWrite(led2B, LOW);
        Serial.println("losing blue led");
      }

      else if ((dur_on >= 5) && (dur_on <= 6)) {
        digitalWrite(led2R, LOW);
        digitalWrite(led2B, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("Neutral");
      }

      else if (dur_on >= interval4) {
        digitalWrite(led2R, HIGH);
        digitalWrite(led2B, LOW);
        Serial.println("red led on");
      }
    }
  }

That's the great advantage of the state-machine approach.

While the button is pressed but the time has not elapsed the system will be in one state
If the button is released without reaching the elapsed time it will switch to whatever other state you want. Something like this pseudo code

if (state == 'H') {
  if ( buttonBstate == LOW){  // assumes LOW = pressed
     state = 'J'
     startStateJmillis = millis()
  }
}
if (state == 'J') {
  if (buttonBstate == HIGH) { // button released
    stateJdurationMillis = millis() - startStateJmillis

    if (stateJdurationMillis > requiredStateJduration) {
       // go on to next state
    }
    else {
        // revert to some earlier state
    }
  }
}

And, an important point, I am assuming this code is called very frequently and the buttonStates are updated very frequently.

...R

Thanks, Robin2 ill try that. After I test everything ill post the complete code.

cro_dude:
Thanks, Robin2 ill try that. After I test everything ill post the complete code.

I realized I had one of my closing braces } in the wrong place in my state == J section in Reply #8. Be sure to look at the revised version.

...R