Arduino Forum

Using Arduino => Programming Questions => Topic started by: loudboy on Apr 07, 2011, 07:30 am

Title: (Resolved) Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 07, 2011, 07:30 am
I'm sure this has come up many times, but I probably wasn't using the right key words when searching :(

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.

Code: [Select]
//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);
   }
}

Title: Re: Continue running one part of code while still checking other inputs?
Post by: bubulindo on Apr 07, 2011, 07:42 am
With a timed interrupt?
Including the checks inside your while loops?
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 07, 2011, 08:04 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: frank26080115 on Apr 07, 2011, 08:24 am
bubulindo's two ideas are both good, I think you mis-understood his suggestions as questions.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: WillR on Apr 07, 2011, 08:32 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: AWOL on Apr 07, 2011, 08:39 am
Quote
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
Title: Re: Continue running one part of code while still checking other inputs?
Post by: WillR on Apr 07, 2011, 09:05 am

Quote
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!
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 07, 2011, 07:47 pm
Edited my post, and I'll check on the "Blink without Delay" method when I get home from work.

oommmmmmmmmmmmmm!!
Title: Re: Continue running one part of code while still checking other inputs?
Post by: TeslaFan on Apr 08, 2011, 01:19 am
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
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 08, 2011, 03:47 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: CrossRoads on Apr 08, 2011, 06:11 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 08, 2011, 06:52 am
He's testing switches:

Code: [Select]
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).
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 08, 2011, 07:58 am
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).
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 08, 2011, 08:02 am
Absolutely. It's not that complicated. You really have two things you need to do:



So the interrupts detect the switch up/downs, and the main loop just flashes stuff.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: CrossRoads on Apr 09, 2011, 01:03 am
"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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: floresta on Apr 09, 2011, 04:38 pm
Quote
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/ (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
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 09, 2011, 09:58 pm
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.



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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 16, 2011, 07:51 am
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?
Title: Re: Continue running one part of code while still checking other inputs?
Post by: floresta on Apr 16, 2011, 03:45 pm
Quote
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
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 17, 2011, 09:09 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 17, 2011, 10:51 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 19, 2011, 05:09 am
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   :( 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?
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 19, 2011, 05:58 am
Try out this code:


Code: [Select]
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:


Code: [Select]
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 20, 2011, 02:22 am
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!
Title: Re: Continue running one part of code while still checking other inputs?
Post by: AWOL on Apr 20, 2011, 08:45 am
Quote
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
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 22, 2011, 12:38 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 22, 2011, 12:48 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: AWOL on Apr 22, 2011, 01:18 am
Quote
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 22, 2011, 05:26 am
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: skyjumper on Apr 22, 2011, 08:29 pm
Do you really need an interupt?

Code: [Select]
#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);   
  }
}


Code: [Select]
// 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
       
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 22, 2011, 11:36 pm
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.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: skyjumper on Apr 22, 2011, 11:41 pm

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.


His app seems very simple, why not try using the Bounce library befoe going to an ISR?
Title: Re: Continue running one part of code while still checking other inputs?
Post by: AWOL on Apr 22, 2011, 11:42 pm
Quote
His app seems very simple, why not try using the Bounce library befoe going to an ISR?

That's what we've been trying to persuade him/her to.
The message doesn't seem to be getting through.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 23, 2011, 12:53 am
Looking back at page 1, two people suggested using interrupts before the original poster.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 04:07 am

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.


I'm using PWM to create a pulsing effect rather than a plain old blinking blinker.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 04:25 am

Quote
His app seems very simple, why not try using the Bounce library befoe going to an ISR?

That's what we've been trying to persuade him/her to.
The message doesn't seem to be getting through.


That's the first mention of a bounce library right there (which is a huge pain in the ass to actually find, BTW. For all the mad coding skills here, this website's search feature sucks.) But now that I have it I'm trying to give it a shot. Probably because I just don't know of the possibilities, but I can't see how this helps me. Is there a Bounce Library Tutorial? Everyone references using the Bounce library, but I cannot for the life of me find anywhere that explains how or why Bounce works (other than keeping a button from chattering when pressed).  Thanks y'all for the help; maybe one of these weeks/months I can find my answers.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 04:53 am
Okay, I've dropped back to basics and am trying to modify the BlinkWithoutDelay sketch to have a button. This seems like it should be easy enough: when the sketch checks the state of the LED to decide if it is already On or not, it has to verify that the blinker switch is as well. Not having much luck. I also tried putting the "&& (LeftBlinkSwitch == HIGH)" in with the section that checks previous Millis against current Millis. I also tried adding "int LeftBlinkSwitchState = LOW;" in with the Variables, but no luck.     Progress?



Code: [Select]

// constants won't change. Used here to
// set pin numbers:
const int LeftBlink =  11;      // I've changed names and pin numbers

const int LeftBlinkSwitch = 8; // added a switch

// Variables will change:
int LeftBlinkState = LOW;             // ledState used to set the LED

long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
 // set the digital pin as output:
 pinMode(LeftBlink, OUTPUT);
 pinMode(LeftBlinkSwitch, INPUT);
 
}

void loop()
{
 // here is where you'd put code that needs to be running all the time.

 // check to see if it's time to blink the LED; that is, if the
 // difference between the current time and last time you blinked
 // the LED is bigger than the interval at which you want to
 // blink the LED.
 unsigned long currentMillis = millis();

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

   // if the LED is off turn it on and vice-versa:
   if ((LeftBlinkState == LOW) && (LeftBlinkSwitch == HIGH)) //*Should* check the state of the LED and the switch
     LeftBlinkState = HIGH;
   else
     LeftBlinkState = LOW;

   // set the LED with the ledState of the variable:
   digitalWrite(LeftBlink, LeftBlinkState);
 }
}
Title: Re: Continue running one part of code while still checking other inputs?
Post by: bilbo on Apr 28, 2011, 05:59 am
Theres nothing super complicate about it. Essentially all you need is the blink without delay sketch, with some extra button checking and blinking.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: CrossRoads on Apr 28, 2011, 06:16 am
need  to read the switch:

if ( (LeftBlinkState == LOW) &&  (digitalRead (LeftBlinkSwitch) == HIGH) )
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 28, 2011, 06:18 am
This works with two lights and two switches. If the switch is grounded (ie. pressed) then it flashes the appropriate light. One light flashes twice as fast as the other:

Code: [Select]
// pin numbers

// switches
const int LeftSwitch = 2;   
const int RightSwitch = 3;

// lights
const int LeftBlink =  11;     
const int RightBlink = 10;

long interval = 500;

void setup()
{
  // set the digital pin as output:
  pinMode(LeftBlink, OUTPUT);
  pinMode(RightBlink, OUTPUT);
 
  // enable pull-ups
  digitalWrite (LeftSwitch, HIGH);
  digitalWrite (RightSwitch, HIGH);
}  // end of setup

void toggleFast ()
{
  if (!digitalRead (LeftSwitch))
    digitalWrite (LeftBlink, !digitalRead (LeftBlink));
  else
    digitalWrite (LeftBlink, LOW);
}  // end of toggleFast

void toggleSlow ()
{
  if (!digitalRead (RightSwitch))
    digitalWrite (RightBlink, !digitalRead (RightBlink));
  else
    digitalWrite (RightBlink, LOW);
}  // end of toggleSlow

void loop()
{
  delay (interval);
  toggleFast ();

  delay (interval);
  toggleFast ();
  toggleSlow ();
 
} // end of loop
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 06:19 am

need  to read the switch:

if ( (LeftBlinkState == LOW) &&  (digitalRead (LeftBlinkSwitch) == HIGH) )



Oh, duh. Thanks  :smiley-red:
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 06:48 am

This works with two lights and two switches. If the switch is grounded (ie. pressed) then it flashes the appropriate light. One light flashes twice as fast as the other:

Code: [Select]
// pin numbers

// switches
const int LeftSwitch = 2;   
const int RightSwitch = 3;

// lights
const int LeftBlink =  11;     
const int RightBlink = 10;

long interval = 500;

void setup()
{
  // set the digital pin as output:
  pinMode(LeftBlink, OUTPUT);
  pinMode(RightBlink, OUTPUT);
 
  // enable pull-ups
  digitalWrite (LeftSwitch, HIGH);
  digitalWrite (RightSwitch, HIGH);
}  // end of setup

void toggleFast ()
{
  if (!digitalRead (LeftSwitch))
    digitalWrite (LeftBlink, !digitalRead (LeftBlink));
  else
    digitalWrite (LeftBlink, LOW);
}  // end of toggleFast

void toggleSlow ()
{
  if (!digitalRead (RightSwitch))
    digitalWrite (RightBlink, !digitalRead (RightBlink));
  else
    digitalWrite (RightBlink, LOW);
}  // end of toggleSlow

void loop()
{
  delay (interval);
  toggleFast ();

  delay (interval);
  toggleFast ();
  toggleSlow ();
 
} // end of loop



Thanks! That code actually flashes the lights UNLESS the switches are pressed/grounded (at least on my setup; my buttons are wired as per example "Push Button Control"). The lights flash, one twice as fast an the other, when the buttons aren't pressed. They turn off when their respective button is pressed.

Is toggleFast() a standard term? I've looked around for an Arduino glossary and have found some useful info, but haven't seen that phrase before. A Google search of the phrase is not helpful...

I also don't understand your use of (!)"not". I understand it when used as a comparator, but not here.

And now that the two lights can blink independent of each other, how can I set the blink rate to be the same? (In my more recently posted sketch I had two different speeds just for distinctions sake) Being blinkers for a vehicle, it makes sense to have them blink at the same speed.  I also need to figure out a brake light with its own behaviors.

Thanks a ton for your help, Nick Gammon! I will keep marching on (somewhat blindly) and see what I can do.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 06:49 am

Theres nothing super complicate about it. Essentially all you need is the blink without delay sketch, with some extra button checking and blinking.


Understood. That little "extra" part has been kicking my ass though.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 28, 2011, 06:53 am

That code actually flashes the lights UNLESS the switches are pressed/grounded (at least on my setup; my buttons are wired as per example "Push Button Control"). The lights flash, one twice as fast an the other, when the buttons aren't pressed.


How did you wire it up? The way I had it, the wires are not connected unless you "press" them which is grounding them. Thus with the pull-ups enabled, the default (off) position is HIGH, and when you press the switch the are LOW.

Hence this:

Code: [Select]
    digitalWrite (LeftBlink, !digitalRead (LeftBlink));

That reads the switch and the "!" is a "not" which means "reverse the logic", true becomes false, false becomes true.


Quote
Is toggleFast() a standard term?


I just made those functions as you can see in the code. You can make your own functions to make the code more modular and easier to read.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 07:24 am
I have my buttons wired as seen in the first breadboard picture here: http://www.ladyada.net/learn/arduino/lesson5.html

But I'm betting you have this: http://arduino.cc/en/Tutorial/Button
I will change my board accordingly, since I didn't have any luck trying to modify the code by deleting the logic reverses.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Apr 28, 2011, 07:36 am


Quote
Is toggleFast() a standard term?


I just made those functions as you can see in the code. You can make your own functions to make the code more modular and easier to read.


I see where you added those functions into the code, but not how you defined them. How does the program know what that means and that it should be linked to the long interval? I see where they are mentioned again in "void loop", but that still doesn't define the term. I'm expecting to see something similar to "const int LeftSwitch = 2;" that links items, but I don't see where that is happening.

I'm still looking for a good reference manual for this stuff, can you suggest a book or website that teaches this? The Arduino Learning site is good, but I see nothing there that relates to your toggleFast trick or my problem here.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on Apr 28, 2011, 10:06 am

I see where you added those functions into the code, but not how you defined them.


I defined it thus:

Code: [Select]

void toggleFast ()
{
  if (!digitalRead (LeftSwitch))
    digitalWrite (LeftBlink, !digitalRead (LeftBlink));
  else
    digitalWrite (LeftBlink, LOW);
}  // end of toggleFast


To be honest, I'm not sure what you are asking me. If I had written:

Code: [Select]
int a = 42;


And you replied "I don't see how you defined a", I would be equally perplexed. I did it right there.

Quote
... can you suggest a book or website that teaches this?


Google "C tutorial" or "C++ tutorial".

There are many, many sites devoted to teaching you C. Find one whose style appeals to you.
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on May 29, 2011, 09:40 pm
Okay, so I decided to come back to this after giving it a break to clear my head. Now I am attacking it again without all the ruts that I seemed to have been stuck in before. I read up more and learned a bit and tried my hand at implementing timed events; posted below is what I came up with. It is close, it is so very close (I think). The problem that I am running into is that my sketch isn't behaving the way I think I have it written.

What I want to happen: When the brake button (momentary switch) is pushed (goes HIGH), the brake light flashes rapidly for one second, then stays on until the brake button is released (goes LOW).

What happens: I press the brake button and it flashes rapidly for as long as the button is held down, up to ~32 seconds after the sketch started running/arduino was turned on. After ~32 seconds has elapsed since the sketch started, the light stays on steady when the switch is pushed without flashing first. It makes no difference if I hold down the button for the whole 32 seconds or not - my interactions with the button have no effect on the 32second phenomena.

Where is this 32 seconds coming from? I've trying looking for other people who have noticed a similar event, but without luck.
Why doesn't the light transition from rapid flash to steady on after one second(1000 millis)?

I've tried removing variables and lines of codes selectively to hunt down the culprit, but haven't had any luck tracing down the culprit there either. Any ideas? Thanks guys, and I hope you are all enjoying your Memorial Day activities!

Code: [Select]
/*A sketch to control the brake lights of a motorcycle,
including an inital attention grabbing rapid-blink sequence lasting one second before staying on steady.
*/

const int BrakeSwitch = 6;
const int BrakeLight = 9;

int BrakeSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)
int BrakeSwitchVal = 0; //Monitors the value of the Brake switch, whether 1 or 0 (HIGH or LOW). Initially set at 0(LOW)
int previousBrakeSwitchVal = 0; //Monitors the value of the Brake switch from last time it was checked. Initally set at 0(LOW)
int BrakeLightState = LOW; //Initial state of the Brake Light. Initally set to LOW(Off)
long previousMillis9 = 0; //Time stamp for when light last went to 1(LOW), initially set at O(LOW)

long interval = 1000; // interval at which to blink (milliseconds)

void setup()
{
  pinMode(BrakeLight, OUTPUT);
  pinMode(BrakeSwitch, INPUT); 
}

void loop()
{
  unsigned long currentMillis = millis(); //initiallizes the clock

  BrakeSwitchVal = digitalRead(BrakeSwitch); //read and store brake switch status
  if ((BrakeSwitchVal == HIGH) && (previousBrakeSwitchVal == LOW)) //compares current switch status to previous status
    previousBrakeSwitchVal = BrakeSwitchVal; //sets the current status as the old status in preparation for the next check
    BrakeSwitchMillis = currentMillis; //sets a time stamp at the current time
   
       if ((BrakeSwitchVal == HIGH) && (currentMillis - BrakeSwitchMillis > interval)) //checks if the brake switch is pressed and how long it has been pressed for
         {
         digitalWrite (BrakeLight, HIGH); //if the switch is being pressed on and it has been pressed for longer than one second, the brake light goes on.
         }
         
         
       else if((BrakeSwitchVal == HIGH) && (currentMillis - previousMillis9 > interval/50)) //if the brake switch is HIGH but less than a second has elapsed, this checks if the brake switch is HIGH
                                                                                             //and more than one-fifteith of a second has elapsed since the last time previousMillis9 was reset.
         {
        previousMillis9 = currentMillis; // saves current time
         
         if (BrakeLightState == LOW)
            BrakeLightState = HIGH;
          else
            BrakeLightState = LOW; //if more than one-fiftieth of a second has elapsed since the time stamp was reset, reverse the state of the brake light.

          // set the LED with the ledState of the variable:
          digitalWrite(BrakeLight, BrakeLightState);
          }
         
         {
     if (BrakeSwitchVal == LOW)
       digitalWrite (BrakeLight, LOW); //Overall, if the brake switch is off, keep the brake light off.     
         }
}

Title: Re: Continue running one part of code while still checking other inputs?
Post by: AWOL on May 29, 2011, 09:48 pm
Quote
up to ~32 seconds

Big clue right there.
Probably about 32.767 (or so) seconds.
That tells me you've got an "int" where you should have a "long".
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on May 29, 2011, 10:37 pm
He's right. And as to why it ignores the switch:

Code: [Select]
int BrakeSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)

...

  BrakeSwitchVal = digitalRead(BrakeSwitch); //read and store brake switch status
  if ((BrakeSwitchVal == HIGH) && (previousBrakeSwitchVal == LOW)) //compares current switch status to previous status
    previousBrakeSwitchVal = BrakeSwitchVal; //sets the current status as the old status in preparation for the next check
  BrakeSwitchMillis = currentMillis; //sets a time stamp at the current time


That last line is done unconditionally (despite your indentation).  If it is supposed to be when you press the switch that is not what you are achieving.

You need the squiggly brackets:

Code: [Select]
BrakeSwitchVal = digitalRead(BrakeSwitch); //read and store brake switch status
  if ((BrakeSwitchVal == HIGH) && (previousBrakeSwitchVal == LOW)) //compares current switch status to previous status
    {
    previousBrakeSwitchVal = BrakeSwitchVal; //sets the current status as the old status in preparation for the next check
    BrakeSwitchMillis = currentMillis; //sets a time stamp at the current time
    }


Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on May 29, 2011, 11:25 pm
Thank you both for the quick replies! I actually realized that I used the wrong time frame shortly after posting. Actually, I finally understood the difference between the two rather than just having made a simple typo.

As for the squiggles, thanks for solidifying what slowely becoming clear; your confirmation makes it stick now :)

I will makes those changes to my sketch, and then see if I can apply what I learned to making my turn signals behave similarly, but with a PWM pulsing blink effect.

Edit: I also had to add a line just before the end to make sure that the BrakeSwitchVal was reset to 0 after the button was released, otherwise the clock wouldnt reset and the initial flash wouldn't occur:   
  if (BrakeSwitchVal == LOW)
         {
           previousBrakeSwitchVal = BrakeSwitchVal; //makes sure the previousBrakeSwitch value is reset of off when the switch is in fact off.
         }



Stay tuned for the next exciting episode of The Adventures of a Coding n00b!
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on May 30, 2011, 06:49 am
Next are the blinkers. I am building the sketch to handle one of them right now, and will simply copy+paste it and change the names to create the other side.

What I want to happen: When the turn signal toggle switch is turned on (HIGH), the associated turn signal should flash rapidly for half a second, then settle into a slower blink rate normally seen on vehicles. When the toggle switch is turned off (LOW), the turn signal light should go off and stay off.

What is happening: When the toggle switch goes HIGH, the blinker flashes rapidly for one half second, then settles into a normal blink rate. However, when the toggle switch goes LOW, the light either goes off completely or it stays half lit at half brightness. In operation there is no obvious pattern to determine whether the light will go off or stay half bright.

What I'm thinking: The half-brightness indicates to me that for some reason the sketch gets caught in a loop of turning the light on and off as fast as it can. I could be wrong though. The final instruction in the sketch dictates that if the state of the toggle switch is LOW, then the light must also be LOW. For some reason, that is not always happening.

Here is the sketch with the rapid-flash portion of the code removed. By process of elimination I found that that part of the code is not the culprit.

Code: [Select]
/*A sketch to control the turn indicator lights of a motorcycle,
including an inital attention grabbing rapid-blink sequence lasting one second followed by pulsing "flashes".
*/

const int RightSwitch = 7;
const int RightBlink = 10;



long RightSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)
int RightSwitchVal = 0; //Monitors the value of the Right Blinker switch, whether 1 or 0 (HIGH or LOW). Initially set at 0(LOW)
int previousRightSwitchVal = 0; //Monitors the value of the Right Blinker switch from last time it was checked. Initally set at 0(LOW)
int RightBlinkState = LOW; //State of the Right Blinker Light. Initally set to LOW(Off)
long FastFlashMillis = 0; //Time stamp for when rapid flash last went to 1(LOW), initially set at O(LOW)
long SlowFlashMillis = 0; //Time stamp for when slow flash last went to 1(LOW), initially set at O(LOW)
int i = 0; //variable used to count up and down for the blinker pulses.

long interval = 1000; // interval at which to blink (milliseconds)

void setup()
{
  pinMode(RightBlink, OUTPUT);
  pinMode(RightSwitch, INPUT); 
}

void loop()
{
  unsigned long currentMillis = millis(); //initiallizes the clock

  RightSwitchVal = digitalRead(RightSwitch); //read and store brake switch status
 
  if ((RightSwitchVal == HIGH) && (previousRightSwitchVal == LOW)) //compares current switch status to previous status
    {
     previousRightSwitchVal = RightSwitchVal; //sets the current status as the old status in preparation for the next check
     RightSwitchMillis = currentMillis; //sets a time stamp at the current time
    }
     if ((RightSwitchVal == HIGH) && (currentMillis - RightSwitchMillis > interval/2) && (currentMillis - SlowFlashMillis > interval/10)) //checks if the Right Blinker switch is pressed and how long it has been pressed for
        {
         SlowFlashMillis = currentMillis; //if the Right Blinker switch is pressed on and has been on for more than half a second, set FastFlashMillis to the current time.
     if (RightBlinkState == LOW)
         RightBlinkState = HIGH;
     else
         RightBlinkState = LOW;  // if the LED is off turn it on and vice-versa
         }   
     digitalWrite(RightBlink, RightBlinkState); // set the Right Blinker to match Right Blink State
         
         
         
     if (RightSwitchVal == LOW)
         {
           previousRightSwitchVal = RightSwitchVal; //makes sure the previousBrakeSwitch value is reset to off when the switch is in fact off.
         }
         
         {
     if (RightSwitchVal == LOW)
       digitalWrite (RightBlink, LOW); //Overall, if the Right Blinker switch is off, keep the Right Blinker off.     
         }
}



And just to be sure, here is the full sketch
Code: [Select]
/*A sketch to control the turn indicator lights of a motorcycle,
including an inital attention grabbing rapid-blink sequence lasting one second followed by pulsing "flashes".
*/

const int RightSwitch = 7;
const int RightBlink = 10;



long RightSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)
int RightSwitchVal = 0; //Monitors the value of the Right Blinker switch, whether 1 or 0 (HIGH or LOW). Initially set at 0(LOW)
int previousRightSwitchVal = 0; //Monitors the value of the Right Blinker switch from last time it was checked. Initally set at 0(LOW)
int RightBlinkState = LOW; //State of the Right Blinker Light. Initally set to LOW(Off)
long FastFlashMillis = 0; //Time stamp for when rapid flash last went to 1(LOW), initially set at O(LOW)
long SlowFlashMillis = 0; //Time stamp for when slow flash last went to 1(LOW), initially set at O(LOW)
int i = 0; //variable used to count up and down for the blinker pulses.

long interval = 1000; // interval at which to blink (milliseconds)

void setup()
{
  pinMode(RightBlink, OUTPUT);
  pinMode(RightSwitch, INPUT); 
}

void loop()
{
  unsigned long currentMillis = millis(); //initiallizes the clock

  RightSwitchVal = digitalRead(RightSwitch); //read and store brake switch status
 
  if ((RightSwitchVal == HIGH) && (previousRightSwitchVal == LOW)) //compares current switch status to previous status
    {
     previousRightSwitchVal = RightSwitchVal; //sets the current status as the old status in preparation for the next check
     RightSwitchMillis = currentMillis; //sets a time stamp at the current time
    }
     if ((RightSwitchVal == HIGH) && (currentMillis - RightSwitchMillis > interval/2) && (currentMillis - SlowFlashMillis > interval/10)) //checks if the Right Blinker switch is pressed and how long it has been pressed for
        {
         SlowFlashMillis = currentMillis; //if the Right Blinker switch is pressed on and has been on for more than half a second, set FastFlashMillis to the current time.
     if (RightBlinkState == LOW)
         RightBlinkState = HIGH;
     else
         RightBlinkState = LOW;  // if the LED is off turn it on and vice-versa
         }
       // set the LED with the ledState of the variable:
     digitalWrite(RightBlink, RightBlinkState);

/*

  for (i = 0; i < 255;i++){ //loop from 0 to 254(fade in)
  analogWrite(RightBlink, i); //set the LED brightness
  delay(10); //Wait 10ms because analogWrite is instantaneous and we would
               //not see a change
  }
  delay(1000); //stay full bright for 1 sec
  for (i = 255; i > 0; i--) {  //loop from 255 to 1 (fade out)
 
  analogWrite(RightBlink, i); //set the LED brightness
  delay(10);
  }
  delay(1000); //stay full off for 1 sec


     
    if((RightSwitchVal == HIGH) && (currentMillis - FastFlashMillis > interval/50) && (currentMillis - RightSwitchMillis < interval/2)) //if the Right Blink switch is HIGH but less than half a second has elapsed,
                                                                                                                                            // this checks if the Right Blink switch is HIGH and more than one-fifteith
                                                                                                                                            //of a second has elapsed since the last time previousMillis10 was reset.
         {
        FastFlashMillis = currentMillis; // saves current time
         
         if (RightBlinkState == LOW)
            RightBlinkState = HIGH;
          else
            RightBlinkState = LOW; //if more than one-fiftieth of a second has elapsed since the time stamp was reset, reverse the state of the Right Blinker.

          // set the Right Blinker with the state of the variable:
          digitalWrite(RightBlink, RightBlinkState);
          }
     */     
         
     if (RightSwitchVal == LOW)
         {
           previousRightSwitchVal = RightSwitchVal; //makes sure the previousBrakeSwitch value is reset of off when the switch is in fact off.
         }
         
         {
     if (RightSwitchVal == LOW)
       digitalWrite (RightBlink, LOW); //Overall, if the Right Blinker switch is off, keep the Right Blinker off.     
         }
}


I do think that I am understanding and getting the hang of the timed events better now though :)
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on May 30, 2011, 07:11 am
This line here:

Code: [Select]
// set the LED with the ledState of the variable:
  digitalWrite(RightBlink, RightBlinkState);


will have a 50% chance of turning it on, once it has been on before.

You probably want:

Code: [Select]

  // set the LED with the ledState of the variable:
  if (RightSwitchVal == HIGH)
    digitalWrite(RightBlink, RightBlinkState);



And I don't know about this:

Code: [Select]
if (RightSwitchVal == LOW)
  {
    previousRightSwitchVal = RightSwitchVal; //makes sure the previousBrakeSwitch value is reset of off when the switch is in fact off.
  }

  {
    if (RightSwitchVal == LOW)
      digitalWrite (RightBlink, LOW); //Overall, if the Right Blinker switch is off, keep the Right Blinker off.     
  }


The second set of squiggly brackets don't do anything, and why not combine them anyway?

Code: [Select]
if (RightSwitchVal == LOW)
  {
  previousRightSwitchVal = RightSwitchVal; //makes sure the previousBrakeSwitch value is reset of off when the switch is in fact off.
  digitalWrite (RightBlink, LOW); //Overall, if the Right Blinker switch is off, keep the Right Blinker off.     
  }
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on May 30, 2011, 07:36 am
Oh, thank you, I see that now. I thought that part falls under the umbrella of the initial condition...

Code: [Select]
if ((RightSwitchVal == HIGH) && (currentMillis - RightSwitchMillis > interval/2) && (currentMillis - SlowFlashMillis > interval/10))

...but I see now how it is all separated. How would I include the secondary if's and operations under the control of that initial condition? I have it formatted with indentation the way I thought it would have work, but obviously that isn't happening. I'll read up on how to do that.

Onward!
Title: Re: Continue running one part of code while still checking other inputs?
Post by: nickgammon on May 30, 2011, 07:53 am
You probably want to nest your ifs. Try  some books on C, it might make it clearer.

For example:

Code: [Select]
if (RightSwitchVal == HIGH)
  {

  // nested condition
  if (previousRightSwitchVal == LOW)
    {

    }  // end of switch high but was low before

  }  // end of RightSwitchVal == HIGH
else

  // must be low then
  {

  // what to do if switch is low

  } // end of RightSwitchVal == LOW
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Jun 03, 2011, 08:41 am
Finished! Done! It works! Thank you so much Nick Gammon for all of your help and support, I really appreciate that.

Here is half the code (it is too long for one posting  :P) It ain't pretty but it works, and I look forward to learning how to make it purtyier  8)

Code: [Select]
/*A sketch to control the indicator lights of a motorcycle,
including an inital attention grabbing rapid-blink sequence lasting one half second followed by pulsing "flashes"
or the brake light holding full bright on.
This is my first "major", functional, purposful sketch. It can proably be slimmed down significantly,
and I look forward to learning the tricks that will let me do that.
I could not have done it without the patient guidance of Nick Gammon and the help AWOL, CrossRoads, and many others.
Thank you.

-Anthony (Loudboy)
*/


const int BrakeSwitch = 6;
const int BrakeLight = 9;

const int RightSwitch = 7;
const int RightBlink = 10;

const int LeftSwitch = 8;
const int LeftBlink = 11;

long BrakeSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)
int BrakeSwitchVal = 0; //Monitors the value of the Brake switch, whether 1 or 0 (HIGH or LOW). Initially set at 0(LOW)
int previousBrakeSwitchVal = 0; //Monitors the value of the Brake switch from last time it was checked. Initally set at 0(LOW)
int BrakeLightState = LOW; //State of the Brake Light. Initally set to LOW(Off)
long previousMillis9 = 0; //Time stamp for when light last went to 1(LOW), initially set at O(LOW)

long RightSwitchMillis = 0; //Time stamp for when the switch last went to 1(HIGH). Initially set at 0(LOW)
int RightSwitchVal = 0; //Monitors the value of the Right Blinker switch, whether 1 or 0 (HIGH or LOW). Initially set at 0(LOW)
int previousRightSwitchVal = 0; //Monitors the value of the Right Blinker switch from last time it was checked. Initally set at 0(LOW)
int RightBlinkState = LOW; //State of the Right Blinker Light. Initally set to LOW(Off)
long RightFlashMillis = 0; //Time stamp for when rapid flash last went to 1(LOW), initially set at O(LOW)
long RightPulseMillis = 0; //Time stamp for when the Right Blinker value i was last adjusted
int R = 0; //variable used to count up and down for the Right Blinker pulses.
int RightPulse = LOW; //variable used to determine Fade In or Fade Out. HIGH means i=225 and going down, LOW means i=0 and going up.

long LeftSwitchMillis = 0;
int LeftSwitchVal = 0;
int previousLeftSwitchVal = 0;
int LeftBlinkState = LOW;
long LeftFlashMillis = 0;
long LeftPulseMillis = 0;
int L = 0;
int LeftPulse = LOW;


long interval = 1000; // interval at which to blink (milliseconds)

void setup()
{
 pinMode(BrakeLight, OUTPUT);
 pinMode(BrakeSwitch, INPUT);
 
 pinMode(RightBlink, OUTPUT);
 pinMode(RightSwitch, INPUT);
 
 pinMode(LeftBlink, OUTPUT);
 pinMode(LeftSwitch, INPUT);
}

void loop()
{
 unsigned long currentMillis = millis(); //initiallizes the clock
 
//Brake Light Code////////////////////////////////////////////////////////////////////////////////////////
BrakeSwitchVal = digitalRead(BrakeSwitch); //read and store brake switch status
 if ((BrakeSwitchVal == HIGH) && (previousBrakeSwitchVal == LOW)) //compares current switch status to previous status
  {
   previousBrakeSwitchVal = BrakeSwitchVal; //sets the current status as the old status in preparation for the next check
   BrakeSwitchMillis = currentMillis; //sets a time stamp at the current time
  }
      if ((BrakeSwitchVal == HIGH) && (currentMillis - BrakeSwitchMillis > interval/2)) //checks if the brake switch is pressed and how long it has been pressed for
        {
        digitalWrite (BrakeLight, HIGH); //if the switch is being pressed on and it has been pressed for longer than one half second, the brake light goes on full and steady.
        }
       
       
      else if((BrakeSwitchVal == HIGH) && (currentMillis - previousMillis9 > interval/50)) //if the above conditions are true, this checks if the brake switch is HIGH
                                                                                            //and more than one-fifteith of a second has elapsed since the last time previousMillis9 was reset.
        {
       previousMillis9 = currentMillis; // saves current time
       
        if (BrakeLightState == LOW)
           BrakeLightState = HIGH;
         else
           BrakeLightState = LOW; //if more than one-fiftieth of a second has elapsed since the time stamp was reset, reverse the state of the brake light.

         
         digitalWrite(BrakeLight, BrakeLightState); // set the LED with the ledState of the variable:
         }
    if (BrakeSwitchVal == LOW)
        {
          previousBrakeSwitchVal = BrakeSwitchVal; //makes sure the previousBrakeSwitch value is reset of off when the switch is in fact off.
          digitalWrite (BrakeLight, LOW); //Overall, if the brake switch is off, keep the brake light off.  
        }
       
Title: Re: Continue running one part of code while still checking other inputs?
Post by: loudboy on Jun 03, 2011, 08:43 am
And here is the second half of the above code. This gets pasted directly under the last part.

Code: [Select]

//Right Blinker Code/////////////////////////////////////////////////////////////////////////////////////////////////////////
  RightSwitchVal = digitalRead(RightSwitch); //read and store Right Blinker switch status
 
  if ((RightSwitchVal == HIGH) && (previousRightSwitchVal == LOW)) //compares current switch status to previous status
    {
     previousRightSwitchVal = RightSwitchVal; //sets the current status as the old status in preparation for the next check
     RightSwitchMillis = currentMillis; //sets a time stamp at the current time
    }

   if ((RightSwitchVal == HIGH) && (currentMillis - RightSwitchMillis > interval/2) && (RightPulse == LOW) && (currentMillis - RightPulseMillis > interval/10000)) //checks if the Right Blinker switch is pressed and how long it has been pressed for,
        {                                                                                                                                                        // if the Pulse was last set LOW, and if it is time for another step in brightness.
         RightPulseMillis = currentMillis; //Time stamp used to check how long since the brightness, i, was last changed
         R++; //Adds 1 to R value. The value of R dictates light brightness
         RightBlinkState = R; //Sets the light brightness to the value of i.
         analogWrite(RightBlink, RightBlinkState); //Sets the blinker brightness to the dictates level. Why I cannot go directly use (RightBlink, R), I do not know...
         }


 
   if (R == 255) //checks value of R
    {
     RightPulse = HIGH; //if R is maxed out at 255, the RightPulse goes HIGH. This lets R decrease.
    }


   
   if ((RightSwitchVal == HIGH) && (currentMillis - RightSwitchMillis > interval/2) && (RightPulse == HIGH) && (currentMillis - RightPulseMillis > interval/10000)) //checks if the Right Blinker switch is pressed and how long it has been pressed for,
        {                                                                                                                                                           // if the Pulse was last set HIGH, and if it is time for another step in brightness.
         RightPulseMillis = currentMillis; //if the Right Blinker switch is pressed on and has been on for more than half a second, set a time stamp for the fade in.
         R--; //Subtracts 1 from R value
         RightBlinkState = R; //Sets the value of light brightness to the value of R
         analogWrite(RightBlink, RightBlinkState); //set the blinker brightness to the value of RightBlinkState
          }
         
   if ((R == 0) && (currentMillis - RightSwitchMillis > interval/2)) // Checks if R is at 0 so that the brightening cycle can repeate. Also checks if the initial rapid flash sequence is over.
    {
      RightPulse = LOW; //if the above conditions are met, reset RightPulse to LOW.
    }


    if((RightSwitchVal == HIGH) && (currentMillis - RightFlashMillis > interval/50) && (currentMillis - RightSwitchMillis < interval/2)) //if the Right Blink switch is HIGH but less than half a second has elapsed,                                                                                                                                 
         {                                                                                                                                 // this checks if the Right Blink switch is HIGH and more than one-fifteith
        RightFlashMillis = currentMillis; // saves current time                                                                             //of a second has elapsed since the last time previousMillis10 was reset.
         
         if (RightBlinkState == LOW)
            RightBlinkState = HIGH;
          else
            RightBlinkState = LOW; //if more than one-fiftieth of a second has elapsed since the time stamp was reset, reverse the state of the Right Blinker.
           
          digitalWrite(RightBlink, RightBlinkState); // set the Right Blinker with the state of the variable:
          }
     
         
    if (RightSwitchVal == LOW) //checks if the Blinker switch is still on or not. If it is off, the following occurs...
         {
           previousRightSwitchVal = RightSwitchVal; //makes sure the previousBrakeSwitch value is reset to off when the switch is in fact off.
           RightBlinkState = LOW; //resets the blinker
           digitalWrite(RightBlink, RightBlinkState); //Overall, if the Right Blinker switch is off, keep the Right Blinker off.
           R = 0; //resets R in preparation for the next usage.
         }
         
//Left Blinker Code. Identical to Right Blinker Code.//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  LeftSwitchVal = digitalRead(LeftSwitch);
 
  if ((LeftSwitchVal == HIGH) && (previousLeftSwitchVal == LOW))
    {
     previousLeftSwitchVal = LeftSwitchVal;
     LeftSwitchMillis = currentMillis;
    }

   if ((LeftSwitchVal == HIGH) && (currentMillis - LeftSwitchMillis > interval/2) && (LeftPulse == LOW) && (currentMillis - LeftPulseMillis > interval/10000))
        {
         LeftPulseMillis = currentMillis;
         L++;
         LeftBlinkState = L;
         analogWrite(LeftBlink, LeftBlinkState);
         }


 
   if (L == 255)
    {
     LeftPulse = HIGH;
    }


   
   if ((LeftSwitchVal == HIGH) && (currentMillis - LeftSwitchMillis > interval/2) && (LeftPulse == HIGH) && (currentMillis - LeftPulseMillis > interval/10000))
        {
         LeftPulseMillis = currentMillis;
         L--;
         LeftBlinkState = L;
         analogWrite(LeftBlink, LeftBlinkState);
          }
         
   if ((L == 0) && (currentMillis - LeftSwitchMillis > interval/2))
    {
      LeftPulse = LOW;
    }


    if((LeftSwitchVal == HIGH) && (currentMillis - LeftFlashMillis > interval/50) && (currentMillis - LeftSwitchMillis < interval/2))                                                                                                                                 
         {
        LeftFlashMillis = currentMillis;
         
         if (LeftBlinkState == LOW)
            LeftBlinkState = HIGH;
          else
            LeftBlinkState = LOW;
           
          digitalWrite(LeftBlink, LeftBlinkState);
          }
     
         
    if (LeftSwitchVal == LOW)
         {
           previousLeftSwitchVal = LeftSwitchVal;
           LeftBlinkState = LOW;
           digitalWrite(LeftBlink, LeftBlinkState);
           L = 0;
         }
         
}
Title: Re: (Resolved) Continue running one part of code while still checking other inputs?
Post by: Roodesign on May 08, 2013, 05:19 pm
Hi there!
Just found this post, I really like your sketch, I hope that I can use it as a core for what I am trying to do:

please go to www.roopod.com (http://ww.roopod.com) to see what I would use this for!

I would have to modify it to use momentary switches to toggle on the turn signals, and toggle them off.  Does anyone have ideas how to do this...I am very new to coding...so glad I found someone's solution and don't have to suffer through all that work!

-roo trimble