1

I'm working on an Arduino sketch where I created two traffic lights, one for normal traffic and one for pedestrians. I created a function for each of these two lights, which loops it through it's cycle (for example: turn yellow, wait 20 seconds, then turn red and wait again). These are called aTrafficlight() and pTrafficlight, where a is the normal light and p the one for the pedestrians. In my loop() function I set a digitalRead for a button. When this button is pressed the traffic lights should cycle through their loops one at a time (so the normal light turns red, pTrafficlight waits a bit, then turns green, blinks a few times, turns red, waits and ends the loop, so it goes to it's original state.)

This all works. But now I want to add a buzzer. This buzzer must beep once a second while the pTrafficlight is red, once a tenth second while it's green and twice per two seconds while it's flashing green.

Here I encountered a few problems: - When waiting in original state (button's not pressed) it seems I can sometimes press the button without reaction because the loop is still going. I need to figure out how to avoid waiting in the loop when buttonState == LOW. (There's a function wait(int sec)) - When the button is pressed, it loops through the cycles. I could just write some kind of loop implementing the traffic light being red and beeping at the same time, but I'd rather keep these seperated. - Same for the double beeps. I do not want the beeping and flashing of the light to be in the same for loop, as it's confusing and difficult to read and understand the code.

Here's my loop():

int buttonState = 0;

void loop(){
  buttonState = digitalRead(pButton);

  if(buttonState == LOW){
    vSet("red");
    pSet("green");

    // This is where I tried to create the sound.
    digitalWrite(pSound, HIGH);
    delay(10);
    digitalWrite(pSound, LOW);
    wait(1);
  } else {
    aTrafficlight();
    pTrafficlight();
  }
}

Is there a way to solve my problems with multithreading? I tried to look it up at arduino.cc and google, but I can't find a way I understand enough to use it in my existing code.

If not, do you have any better suggestions?

2
  • 1
    This requires a different programming technique, based on a state machine. It is common in games, google "game loop". Basic hit is en.wikipedia.org/wiki/Game_programming#Game_structure Commented Feb 2, 2012 at 12:05
  • Why don't you use interrupts? This way you can invoke an interrupt handler periodically without even having the loop or blocking anything... Commented Feb 3, 2012 at 22:02

2 Answers 2

3

You don't need multi-threading. You need to use timers, whether via interrupts (as Pawel wrote) or via another mechanism, such as the Metro library, that lets the code continue to loop through while the timer is running. See this question and answer: How Can I Create Interrupts in C for Arduino

Coincidentally, I recently posted some material both on state machines and the Arduino, as Hans Passant mentioned, and on alternatives to delay(), both with additional references you might find useful.

Sign up to request clarification or add additional context in comments.

Comments

0

You could use a time-slice design. Let me just outline this in very general terms. First code loop so that it always issues a delay(1) and set a mod 10 counter as:

 int stopWhen = -1;  // at startup
 // etc.
 x = (x+1)%10;       // every time loop execs

Then when buttonState == LOW

 if (stopwWhen = -1)
 {
    stopWhen = x;
    // beep etc.
 }

But on every loop:

 // always exec this:
 if (stopWhen == x)
 {
    stopWhen = -1;
    // stop beeping.
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.