(Resolved) Continue running one part of code while still checking other inputs?

I’m sure this has come up many times, but I probably wasn’t using the right key words when searching :frowning:

The code inserted below is what I am using to run the lights for my motorcycle. All the lights are functioning just fine by themselves, but I need to get multiple things to happen at once. Specifically, if my blinker is on my brake light cant come on and visa-versa. This makes sense now because of the “while” loops I use to trap the Arduino into constantly checking the status of the blinker/brake switch. How can I get my blinker to respond appropriately while the brake light is on, or any combination of that? Thanks.

//A sketch to run the LED lights on the cafe racer.

//Headlight - No code needed to run. Headlight switch will run this like normal, 
//with the addition of a self contained blue LED for Hi-Beam indicator. Also use
//as a button to indicate taillight running light status.

//Taillight - Use PWM to run the brakelight at ~1/2 brightness when headlight is on.
 //Brakelight on a MOSFET.
//Brake light - Use PWM to run brake light at full brightness when either brake is used.
 //Brake light will flash on and off four times in rapid succession before holding at 100%
 //Brake lights on a MOSFET.
 
//Blinkers - Rapidly flash proper blinker light five times before settling into normal blink rate.
//Sets separate buttons for left and right blinker.


const int LeftBlink = 11; //left blinker output
const int RightBlink = 10; //right blinker output
const int BrakeLight = 9; //taillight/brakelight output
const int LeftBlinkSwitch = 8; //right blinker switch input
const int RightBlinkSwitch = 7; //left blinker switch input
const int FrontBrake = 6; //front brake switch input
const int BackBrake = 5; //back brake switch input
const int Headlight = 4; //headlight on/off? input

int i = 0; //used to count the pulse

int LeftBlinkSwitchState = 0;
int RightBlinkSwitchState = 0;
int FrontBrakeState = 0;
int BackBrakeState = 0;
int HeadlightState = 0;

void setup() 
{
    pinMode(LeftBlink, OUTPUT); //defines LeftBlink as an output
    pinMode(RightBlink, OUTPUT); //defines RightBlink as an output
    pinMode(BrakeLight, OUTPUT); //defines Tail as an output
    pinMode(LeftBlinkSwitch, INPUT); //defines LeftBlinkSwitch as an input
    pinMode(RightBlinkSwitch, INPUT); //defines RightBlinkSwitch as an input
    pinMode(FrontBrake, INPUT); //defines FontBrake as an input
    pinMode(BackBrake, INPUT); //defines BackBrake as an input 
    pinMode(Headlight, INPUT); //defines Headlight as an input
}

void loop() 
{
 LeftBlinkSwitchState = digitalRead(LeftBlinkSwitch); //reads the switch value
 RightBlinkSwitchState = digitalRead(RightBlinkSwitch);
 FrontBrakeState = digitalRead(FrontBrake);
 BackBrakeState = digitalRead(BackBrake);
 HeadlightState = digitalRead(Headlight);

////////Start Left Blinker Code//////
 if(LeftBlinkSwitchState == HIGH)  //if the left blinker switch is on, then...
  {
    analogWrite(LeftBlink, 225); //starts initial rapid blink
    delay(50);
    analogWrite(LeftBlink, 0);
    delay(50);
    analogWrite(LeftBlink, 225);
    delay(50);
    analogWrite(LeftBlink, 0);
    delay(50);
    analogWrite(LeftBlink, 225);
    delay(50);
    analogWrite(LeftBlink, 0);
    delay(50);
    analogWrite(LeftBlink, 225);
    delay(50);
    analogWrite(LeftBlink, 0);
    delay(50);
    analogWrite(LeftBlink, 225);
    delay(50);
    analogWrite(LeftBlink, 0);
    delay(50);           //ends initial rapid blink
   }
  
  else
   {
    analogWrite(LeftBlink, 0);
   }
  
  while(LeftBlinkSwitchState == HIGH)  //if the left blinker switch is on, then...
   //start pulse
     {
       for (i = 0; i < 255;i++) //loop from 0 to 254(fade in)
        {
         analogWrite(LeftBlink, i); //set the brightness
         delay(1.5); //Wait because analogWrite is instantaneous and we would not see a change       
        }
        
       for (i = 255; i > 0; i--)  //loop from 255 to 1 (fade out)
        {
         analogWrite(LeftBlink, i); //set the brightness
         delay(1.5);
        }
        
      delay(1); //stay full off
        
      //end pulse
      
      LeftBlinkSwitchState= digitalRead(LeftBlinkSwitch); //checks to see if blinker switch is still on
     }
////////End Left Blinker Code///////////////
////////Start Right Blinker Code//////
 if(RightBlinkSwitchState == HIGH)  //if the right blinker switch is on, then...
  {
    analogWrite(RightBlink, 225); //starts initial rapid blink
    delay(50);
    analogWrite(RightBlink, 0);
    delay(50);
    analogWrite(RightBlink, 225);
    delay(50);
    analogWrite(RightBlink, 0);
    delay(50);
    analogWrite(RightBlink, 225);
    delay(50);
    analogWrite(RightBlink, 0);
    delay(50);
    analogWrite(RightBlink, 225);
    delay(50);
    analogWrite(RightBlink, 0);
    delay(50);
    analogWrite(RightBlink, 225);
    delay(50);
    analogWrite(RightBlink, 0);
    delay(50);           //ends initial rapid blink
   }
  
  else
   {
    analogWrite(RightBlink, 0);
   }
  
  while(RightBlinkSwitchState == HIGH)  //if the right blinker switch is on, then...
   //start pulse
     {
       for (i = 0; i < 255;i++) //loop from 0 to 254(fade in)
        {
         analogWrite(RightBlink, i); //set the brightness
         delay(1); //Wait because analogWrite is instantaneous and we would not see a change       
        }
        
       for (i = 255; i > 0; i--)  //loop from 255 to 1 (fade out)
        {
         analogWrite(RightBlink, i); //set the brightness
         delay(1);
        }
        
      delay(1); //stay full off
        
      //end pulse
     
      RightBlinkSwitchState= digitalRead(RightBlinkSwitch); //checks to see if blinker switch is still on
     }
////////End Right Blinker Code///////////////
////////Start Brake Light Code///////////////
  if (FrontBrakeState == HIGH || BackBrakeState == HIGH)  //if either brake is on, then...
    {
      analogWrite(BrakeLight, 225); //starts initial rapid blink
      delay(45);
      analogWrite(BrakeLight, 0);
      delay(45);
      analogWrite(BrakeLight, 225);
      delay(45);
      analogWrite(BrakeLight, 0);
      delay(45);
      analogWrite(BrakeLight, 225);
      delay(45);
      analogWrite(BrakeLight, 0);
      delay(45);
      analogWrite(BrakeLight, 225);
      delay(45);
      analogWrite(BrakeLight, 0);
      delay(45);
      analogWrite(BrakeLight, 225);
      delay(45);
      analogWrite(BrakeLight, 0);
      delay(45);           //ends initial rapid blink
     }
  
  else if(HeadlightState == HIGH)
   {
    analogWrite(BrakeLight, 112); //if the headlight is on, run the brakelight at 1/2 bright
   }
  else
  {
    analogWrite(BrakeLight, 0); //if the headlight isnt on and no brake is on, turn the braikelight off
  }
  while((FrontBrakeState == HIGH || BackBrakeState == HIGH))
    {
      digitalWrite(BrakeLight, HIGH);
      FrontBrakeState= digitalRead(FrontBrake);
      BackBrakeState= digitalRead(BackBrake);
    }
}

With a timed interrupt?
Including the checks inside your while loops?

Not necessarily. If you know of another way that would work, I'm all ears.

All I want is an end result that behaves like any car brakelight and blinker, with the addition of the flash sequences.

Learning to code better is the ongoing goal of course, and if there is a trick to having Adruino perform one function while checking on others I would love to learn it.

Thanks.

bubulindo's two ideas are both good, I think you mis-understood his suggestions as questions.

Use of the interrupts is a good suggestion...

Maybe you can edit your post and put the code inside the Cross-hatch marks (#). The third-from-the-right button above the smilies.

but I need to get multiple things to happen at once

Let us all intone the mantra:

Check the "Blink without Delay" example, without delay.

Ommmmm

AWOL:

but I need to get multiple things to happen at once

Let us all intone the mantra:

Check the "Blink without Delay" example, without delay.

Ommmmm

Ommmmm!

Edited my post, and I'll check on the "Blink without Delay" method when I get home from work.

oommmmmmmmmmmmmm!!

Blink without delay is a great start but it can get really confusing after you add in a bunch of different events. I use this simple event manager in all my stuff:

http://roboticcore.com/?p=14

I seem to recall there was a question recently about handling multiple interrupts in a sketch. And I also recall that Crossroads pointed out that by judicious use of diodes you can connect multiple switches to a single interrupt pin (eg, pin 2), in addition to being wired to their own unique pins.

That way, with minimal effort you first get an interrupt (as all switches are connected to the interrupt pin), and then you just check by reading the other pins which one must have changed. The diodes stop cross-talking between the switches.

The Diode AND is for reading switch inputs, which would be good to get things started.

Sounds like the solution requested was for things that were running in which case a solution more like checking the on/off state of the ligts every 10mS or something & turn of/off as needed would be better. Record the time something started, check if the end time to turn if off has been reached. I do the same with a fencing scoring machine, but testing every 100uS. So 10mS for some lights would not be a stretch of a performance.

He's testing switches:

 LeftBlinkSwitchState = digitalRead(LeftBlinkSwitch); //reads the switch value

...

////////Start Left Blinker Code//////
 if(LeftBlinkSwitchState == HIGH)  //if the left blinker switch is on, then...
  {
    analogWrite(LeftBlink, 225); //starts initial rapid blink

Here's my tentative solution... Use the Crossroads-diode solution for the switches. Have interrupts to determine switch-state changes. In the interrupt routine turn on/off flags indicating which switches are currently down. Have a main loop that blinks things. In the main loop, where you blink/unblink just turn on the things whose corresponding switches are on, and leave off the others. That way they all blink (the ones that are supposed to) and not only that, they blink together (unlike some gadgets I have here).

Okay, I'll have to do some research on this diode gate stuff, I'm still pretty new at all this.

The event manager seems promising, thanks for the link TeslaFan.

Reading through these suggestions I don't know if I can keep the initial rapid flash followed by pulse (blinker), or followed by steady-on (brake light). If I'm just going to use these interrupts and diodes and whatnot just to come back to plain old blinking, I'll just keep things simple and use the stock equipment. Can I keep my original flashing idea AND use these work-arounds?

I'd really like to keep the rapid flash since it is such a great attention getter (read: life saver).

Absolutely. It's not that complicated. You really have two things you need to do:

  • Detect switch changes (on/off)
  • Flash lights - how many depends on which switches are on (and the rate might depend on how recently the switch was pushed)

So the interrupts detect the switch up/downs, and the main loop just flashes stuff.

"rapid flash" rapid is all relative. On/of 5 times a second vs 1 times a second is hardly rapid electronically. Yet visually it may seem a world of difference, and depending on the viewing distance may blur into always on even.

Okay, I'll have to do some research on this diode gate stuff, I'm still pretty new at all this.

You really should look into implementing the 'Pin Change Interrupts' that are inherent to the ATmega chip used in the Arduino. Essentially any of the I/O pins on the chip can be configured to generate an interrupt when the level on that pin changes. These interrupts are not as configurable as the 'External Interrupts' used by the 'attachInterrupt' function but they do work nicely.

[EDIT:] I found some information on this at http://forums.trossenrobotics.com/tutorials/how-to-diy-128/an-introduction-to-interrupts-3248/ scroll down to the part headed 'Wait, I ran out of interrupts!'. Everything there applies equally to the ATmega328 so don't let the reference to the 168 put you off.

Don

Okay, I think I'm starting to get it. I can have both flash speeds "running" in the background, but only call them when needed and if a time has gone by. I'll draw up a flowchart and post it to see if I can make this all make sense.

[quote author=Nick Gammon link=topic=57812.msg416249#msg416249 date=1302242525] Absolutely. It's not that complicated. You really have two things you need to do:

  • Detect switch changes (on/off)
  • Flash lights - how many depends on which switches are on (and the rate might depend on how recently the switch was pushed)

So the interrupts detect the switch up/downs, and the main loop just flashes stuff. [/quote]

In looking into the Interrupts idea you suggested Floresta, I see that I cannot use delay() while inside the interrupt. I'm looking into a workaround, but it seems that if I use the interrupt method I can't do the blinking that I need. Unless there is another method to blink that I am not seeing?

I see that I cannot use delay() while inside the interrupt.

In general you never want to do very much inside any interrupt. What you should do is set some sort of flag to indicate that some condition has been detected and then exit the interrupt as quickly as possible. Your main program should check the flag and react to the detected condition as required.

Don

So how is reacting to a flag any different than reacting to a physical button input? The Arduino will still be able to pump out only one set of LED instructions at a time whether it is triggered by a button or a flag, right? I need lights to react independent of each other, and continuously (overlapping).

I need the brake light to be able to come on and off regardless of whether a blinker is on, and visa versa.

Even with all these fancy tricks, what I’m understanding is that the Arduino will still only be able to react to one input at a time.