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

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 Trossen Robotics Community Database Error 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.

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.

It reacts by noticing the input. That doesn't mean it can only do one thing afterwards.

Here's an example. You notice the cat is hungry. So you feed it once a day. You notice the garden needs watering. So you water it once a week. You notice the car needs washing. So you wash it once a month.

But that doesn't mean that if the car needs washing, you don't feed the cat.

As a person you build up in your brain a list of things that need doing from time to time. You may check that list every hour, or minute, or second even. And if the time is up to do something ("oh, time to water the garden") you do it.

So your program does the same thing.

Okay, that makes sense. Problem is, I need to weed the garden while washing the car. Or feed the cat while weeding the garden while washing the car, then stop feeding the cat while still washing the car, and then start feeding the cat again while STILL washing the car and weeding the garden.

Or wash the garden while feeding the car and weeding the cat, even.

It does me no good for my brake light to come on whenever it feels like it. I need my brake light to turn on immediately upon pressing the brake, even if my turn signal is on, and I'd prefer to have the attention grabbing rapid flash sequence fire at the start of either light coming on.

I understand now (I think) how I can have my brake light be turned on or off depending on what it's previous state was, and I think I can do the same with the blinking pattern for the blinkers, but I would have to omit the initial rapid-flash sequence :frowning: Which, if that is the case, I'll just chuck the whole Arduino idea and go back to the stock system.

Or am I being a completely infuriating ass and not understanding something here?

Try out this code:

void setup() {
  pinMode (13,OUTPUT);
} //end of setup

void loop() {

if ((millis () & 0x7F) < 63)
  digitalWrite(13, HIGH);
else
  digitalWrite(13, LOW);

}

As you go through the main loop, it flashes an LED quite fast.

Now put a condition on it:

void setup() {
  pinMode (13,OUTPUT);
} //end of setup

void loop() {

if ((millis () & 0x7F) < 63 && indicator_button_down)
  digitalWrite(13, HIGH);   // only flash light if indicator button is on
else
  digitalWrite(13, LOW);

}

The condition is what is set in the interrupt routine. And after that you could flash a different LED, at a different rate, depending on if another condition is set.

So in this way all the speeds of flashing are running in the background, but aren't actually being called until needed? Okay, I can see that. I have some "yea, but"s about it still, but I'll play with it first to see if I can answer my own questions before asking.

Thanks for your help and patience!

So in this way all the speeds of flashing are running in the background

In a way, yes.
Stop and think about it.
Once a LED is lit, or shut off, it stays in that state - you don't have to refresh it, and it stays in that state for the vast majority of the time.
The only time the processor is involved is at the transitions from on to off or vice versa, and these transitions take very little time; just long enough to toggle a variable and write to a port.
A microsecond or so, allowing for Arduino overheads.
You could do thousands of these transitions per second, and a human user would perceive all the operations as concurrent

Except if I were running a pulse width modulation, right? Yes, those thousands of transitions would be happening every second, but the processor would be stuck thinking about that transition and not much else. Or is that also so "slow" that other operations could still continue?

I guess the solution there would just be to drop the PWM pulsing of the brake light and go for normal on/off blink.

I think I'm slowly coming around to seeing how this is possible. Once I wrap my head around that then I should be able to program it in.

I don't think you have to PWM brake lights. My own tests show that much faster than around 50Hz is invisible (that is, too fast to see). And the processor clock is 16 MHz.

Except if I were running a pulse width modulation, right?

Even if you were running PWM, so yes, wrong.

The processor isn't involved in the PWM operation, beyond setting the registers - all the PWM is handled by logic, as a simple peripheral, just like the processor isn't sampling the serial input at 16 times the baud rate to find the initial edge and middle of a start bit.

Oh, cool then. I had assumed that the processor was handling all that, but if it's just throwing that bone to another component then we are in business. I'm still working in what I think is the right direction, so we'll see where I end up. Thanks for your help.

Do you really need an interupt?

#include "Led.h"
#include "constants.h"
#include <WProgram.h>

Led::Led(unsigned char pin, unsigned char initialState, unsigned short fi, unsigned short si)
{
  this->pin = pin;
  mode = initialState;
  pinMode(pin, OUTPUT);

  fastInt = fi;
  slowInt = si;

  update();
}

Led::~Led(){}

void Led::setFastInterval(unsigned short fi)
{
  fastInt = fi;
}

void Led::setSlowInterval(unsigned short si)
{
  slowInt = si;
}  

void Led::slow()
{
  mode = LED_SLOW_BLINK;
  update();
}

void Led::fast()
{
  mode = LED_FAST_BLINK;
  update();
}

void Led::on()
{
  mode = LED_ON;
  update();
}

void Led::off()
{
  mode = LED_OFF;
  update();
}    

void Led::reverse(void)
{
  if(mode != LED_ON && mode != LED_OFF)
  {
    mode = LED_ON;
  }

  if(mode == LED_ON)
  {
    mode = LED_OFF;
  }
  else
  {
    mode = LED_ON;
  }
  
  update();
  
}


void Led::update(void)
{
  short interval = 0;
    
  if(mode == LED_ON)
  {
    state = LED_ON;
  }

  if(mode == LED_OFF)
  {
    state = LED_OFF;
  }
  
  if(mode == LED_FAST_BLINK)
  {
    interval = fastInt;    
  }

  if(mode == LED_SLOW_BLINK)
  {
    interval = slowInt;
  }

  if(mode == LED_SLOW_BLINK || mode == LED_FAST_BLINK)
  {

    if(millis() - lastMs > interval)
    {
      // save the last time you blinked the LED 
      lastMs = millis();   

      // if the LED is off turn it on and vice-versa:
      if(state == LED_ON)
      {
        state = LED_OFF;
      }  
      else
      {
        state = LED_ON;
      }
    }  
  }

  if(state == LED_ON)
  {
    digitalWrite(pin, LOW);
  }

  if(state == LED_OFF)
  {
    digitalWrite(pin, HIGH);   
  }
}
// Led.h

#ifndef LED_H
#define LED_H

#include "constants.h"

class Led
{
  public:

  Led(unsigned char pin, unsigned char initialState = LED_OFF, unsigned short fi = 100, unsigned short si = 750);
  ~Led(void);
  
  void setFastInterval(unsigned short fi);
  void setSlowInterval(unsigned short si);
  void slow(void);
  void fast(void);
  void on(void);
  void off(void);
  void reverse(void);

  void update(void);

  private:
  
  unsigned char pin;
  unsigned long lastMs;
  unsigned char mode;
  unsigned char state;
  unsigned short millDiff;
  
  unsigned short fastInt;
  unsigned short slowInt;
};

#endif

Huh? The interrupt could be used to detect the switch press, not to flash the LEDs. However if you go through the main loop fast enough a simple digitalRead should do it.