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

I'm using PWM to create a pulsing effect rather than a plain old blinking blinker.

AWOL:

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.

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?

// 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);
  }
}

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

need to read the switch:

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

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:

// 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

CrossRoads:
need to read the switch:

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

Oh, duh. Thanks :blush:

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.

bilbo:
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.

loudboy:
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:

    digitalWrite (LeftBlink, !digitalRead (LeftBlink));

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

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 have my buttons wired as seen in the first breadboard picture here: Arduino Tutorial - Lesson 5

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.

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.

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

I defined it thus:

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:

int a = 42;

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

... 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.

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!

/*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.      
         }
}

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".

He's right. And as to why it ignores the switch:

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:

 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
    }

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 :slight_smile:

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!

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.

/*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

/*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 :slight_smile:

This line here:

// 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:

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

And I don't know about this:

 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?

 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.      
  }

Oh, thank you, I see that now. I thought that part falls under the umbrella of the initial condition...

 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!