Go Down

Topic: Best approach - Button press to stop blinking light game - Replace delay (Read 153 times) previous topic - next topic

Doug101

Not looking for the code, just want to make sure this is a good approach and there's not a better way. 
My students have built a copy of an arcade game.  Using a 2560 they built a circle of 40 lights.  The lights chance around in a circle and the object of the game is to press a button to stop the chase when a specific light is lit.

Code so far involves using a for loop for pins 2 - 42.  For loop makes one pin high, delay pin low, next.

But now need to add code if button press = when pin 22 is high (LED on) go to win routine.  If button press is not when 22 high go to you lose routine.

Can't use the delay as we need to test for button press at the same time.  Would the best approach be millis()

Or is there a better way?

The other think I've been thinking is should the button press code be before the pin high code or after.  (Or maybe it doesn't matter as the human pressing the game is slower.

Appreciate the advice.

vaj4088

If you want to be able to do something while waiting for some time to pass, millis() or micros() should be used.  There are other ways (such as interrupts) that present great challenges.  If you need help, there is a locked topic near the top of this forum that is a tutorial on millis().

I do not think that the order will really matter.

Hutkikz

 You're right that delay() will interfere with button reading as it is "blocking" code meaning it blocks other code from running until it's finished.
You may not realize that a for loop(any loop) is also blocking code and will prevent anything outside of the loop i.e. the button from being read.

 Since you haven't posted your code, I can only guess that what's needed is to implement a timing sequence to replace the delay as suggested by vaj4088 and to replace the for loop with a conditional statement( an if statement or a state machine).

PaulMurrayCbr

Generally, the loop method should not delay. This means that it runs in a few microseconds.

Look at it this way: each time loop() runs, it has to ask and answer the question: "is there anything I need to do right now". Or, to put it another way, "has anything in the world changed since the last time I was executed?" In the case of this sketch, there are two important things that might change: millis() can tick over, and pin 22 might change state.

so, loop() looks like this:

Code: [Select]

byte state_of_pin_22_last_time_i_executed;
int which_light_is_currently_on;
uint32_t time_at_which_the_current_light_got_turned_on;

void loop() {
  if pin 22 has changed from HIGH to LOW
    do whatever I need to do to handle a button press
    remember the new current state of pin 22
  end


  if it's now time to turn the current light off and the next one on
    turn the current light off and the next one on
    remember which light is now on and when I turned it on
  end if
}
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

Doug101

I haven't done any coding yet..... I'm asking what the best approach would be.

I know I can't use delay as that's effectily pauses the program.

But can't I use a for loop?  And in the for loop have a conditional if statement. 
If lLED is lit when button is pressed goto win
If LED not lt when button is pressed go to lose.

I haven't tried this but you can break out of a for loop correct?

Or would a while loop be better?


Can you give a couple of quick examples of when one would use a for vs. while loop?

Thanks


Hutkikz

 As PaulMurrayCbr mentioned a loop(any loop) isn't a problem if it only takes a few microseconds to complete. The longer it takes and it starts becoming a problem. From your description it sounds as there is a high probability it could take too long but testing is the only way to be sure.

A for loop is generally used to iterate a specific number of times. 
Code: [Select]
for (byte i = 2; i < 43; i++)
{
  pinMode ( i, OUTPUT); // Set pins 2-42 to outputs
}

A while loop repeatedly executes as long as a given condition is true.
Code: [Select]
while (digitalRead(button))
{
  Serial.println ("Press button to exit this loop"); // continually print this till the button is pushed
}

And yes it is possible to break out of a loop, but it's somewhat rare to need to.

 The take away here is that loops ARE blocking code and as such should be kept short.


 

Doug101

You're right that delay() will interfere with button reading as it is "blocking" code meaning it blocks other code from running until it's finished.
You may not realize that a for loop(any loop) is also blocking code and will prevent anything outside of the loop i.e. the button from being read.

 Since you haven't posted your code, I can only guess that what's needed is to implement a timing sequence to replace the delay as suggested by vaj4088 and to replace the for loop with a conditional statement( an if statement or a state machine).
I will post my code soon.  I have a about 60% of it working without using for loops.  Adding one for loop removed 45 lines of code.


Right now I'm trying to get rid of another 100 or so lines of code.

I'm working on small block of code to get them working before incorporating into my master code.

I'm really close.








Go Up