Blinking without stoping the code.

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
duffkindt
 
Posts: 3
Joined: Thu Feb 10, 2011 2:37 pm

Blinking without stoping the code.

Post by duffkindt »

I have tried several ways to get this to happen but to no avail. I am a newbe and was pleased to get my basic sketch to work fine but adding the blink in several different ways didn't work. i have spent two weeks trying to find a solution. It must be right under my nose. I'm 62 yo and this is my first programming effort my brain must be atrophying. Code follows.

/*Sequence 7-10 lights from bottom to top of driveway
or top to bottom from PIR input at top or bottom.
If top sequences is initiated first the top most
and bottom most light will light first,
then top to bottom sequence will continue
until complete then remain on for one minute
then all will go off. The same if the bottom
sequence is initiated first only in reverse. */
/*Added whistle blink the led at the oppisite end of
the driveway to indicate if soomeone is coming up,
or down as the case may be*/
// Initialize pins as input and output

int topPir = 2; //digital input for top pir
int bottomPir = 3; //digital input for bottom pir

int outPin4 = 4; //output for bottom light or relay
int outPin5 = 5;
int outPin6 = 6;
int outPin7 = 7;
int outPin8 = 8;
int outPin9 = 9;
int outPin10 = 10;
int outPin11 = 11;
int outPin12 = 12; //output for top light or relay

void setup()
{
pinMode(topPir, INPUT); //declare topPir as input
pinMode(bottomPir, INPUT); //declare bottomPir as input
pinMode(outPin4, OUTPUT); // declare outPin4 as output
pinMode(outPin5, OUTPUT); // declare outPin5 as output
pinMode(outPin6, OUTPUT); // declare outPin6 as output
pinMode(outPin7, OUTPUT); // declare outPin7 as output
pinMode(outPin8, OUTPUT); // declare outPin8 as output
pinMode(outPin9, OUTPUT); // declare outPin9 as output
pinMode(outPin10, OUTPUT); // declare outPin10 as output
pinMode(outPin11, OUTPUT); // declare outPin11 as output
pinMode(outPin12, OUTPUT); // declare outPin12 as outputq
}

void loop ()
{
if (digitalRead(topPir) == HIGH)//checks topPir condition
{
digitalWrite(outPin4, HIGH); //turns output outPin4 on
digitalWrite(outPin12, HIGH); //I want to blink this one
delay(1000); //delays for one second
digitalWrite(outPin5, HIGH); //turn on output outPin5
delay(1000); //delay
digitalWrite(outPin6, HIGH); //same as above until end of
delay(1000); //loop
digitalWrite(outPin7, HIGH);
delay(1000);
digitalWrite(outPin8, HIGH);
delay(1000);
digitalWrite(outPin9, HIGH);
delay(1000);
digitalWrite(outPin10, HIGH);
delay(1000);
digitalWrite(outPin11, HIGH);
delay(1000);
digitalWrite(outPin12, HIGH);
delay(60000); //all outputs on for one minute
digitalWrite(outPin4, LOW); //turns all outPins off
digitalWrite(outPin5, LOW);
digitalWrite(outPin6, LOW);
digitalWrite(outPin7, LOW);
digitalWrite(outPin8, LOW);
digitalWrite(outPin9, LOW);
digitalWrite(outPin10, LOW);
digitalWrite(outPin11, LOW);
digitalWrite(outPin12, LOW);
}
if (digitalRead(bottomPir) == HIGH)//checks bottomPir condition
{
digitalWrite(outPin12, HIGH); //turns output outPin12 on
digitalWrite(outPin4, HIGH); // blink this while rest of code runs
delay(1000); //delays for one second
digitalWrite(outPin11, HIGH); //turn on output outPin12
delay(1000); //delay
digitalWrite(outPin10, HIGH); //same as above until end of
delay(1000); //loop
digitalWrite(outPin9, HIGH);
delay(1000);
digitalWrite(outPin8, HIGH);
delay(1000);
digitalWrite(outPin7, HIGH);
delay(1000);
digitalWrite(outPin6, HIGH);
delay(1000);
digitalWrite(outPin5, HIGH);
delay(1000);
digitalWrite(outPin4, HIGH);
delay(60000); //all outputs on for one minute
digitalWrite(outPin4, LOW); //turns all outPins off
digitalWrite(outPin5, LOW);
digitalWrite(outPin6, LOW);
digitalWrite(outPin7, LOW);
digitalWrite(outPin8, LOW);
digitalWrite(outPin9, LOW);
digitalWrite(outPin10, LOW);
digitalWrite(outPin11, LOW);
digitalWrite(outPin12, LOW);
}

}

Thanks Duff

User avatar
westfw
 
Posts: 2008
Joined: Fri Apr 27, 2007 1:01 pm

Re: Blinking without stoping the code.

Post by westfw »

There is the "blink without delay" example sketch...

Many of the examples are missing a description of the thought process that leads to the code they contain. The basic strategy for blinking is essentially

Code: Select all

if (time_to_change_ledstate(which_led) {
   change_led_state(which_led);
   set_new_time_to_change(which_led);
}
BlinkWithoutDelay is an example of a way to implement this.

duffkindt
 
Posts: 3
Joined: Thu Feb 10, 2011 2:37 pm

Re: Blinking without stoping the code.

Post by duffkindt »

I'm sorry. I don't understand.
Would I place this statement below my initial if statement or inside of it?

if (time_to_change_ledstate(which_led) {
change_led_state(which_led);
set_new_time_to_change(which_led);
}


Does "time_to_change_ledstate" refer to a number of milliseconds or a point at which I want the blinking to start? i.e. topPir==HIGH?
I would think (which_led) in my case would be outPin12.
Is change_led_state some sort of command that I need to declare as a variable and give an initial value?
Lastly (I hope) set_new_time_to_change would be the rate of change i.e. 300milliseconds?

I really feel dumb but I am trying.
Thanks, Duff

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: Blinking without stoping the code.

Post by adafruit_support_bill »

The "BlinkWithoutDelay" example sketch in the IDE is a good place to start. This uses a system timer (millis) to figure out when it is time to change the state of the LED. Once you understand how it works for one LED, you should be able scale it up to sequence multiple LEDs.

Code: Select all

/* Blink without Delay
 
 Turns on and off a light emitting diode(LED) connected to a digital  
 pin, without using the delay() function.  This means that other code
 can run at the same time without being interrupted by the LED code.
 
 The circuit:
 * LED attached from pin 13 to ground.
 * Note: on most Arduinos, there is already an LED on the board
 that's attached to pin 13, so no hardware is needed for this example.
 
 
 created 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 
 This example code is in the public domain.

 
 http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
 */

// constants won't change. Used here to 
// set pin numbers:
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = 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(ledPin, OUTPUT);      
}

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 (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

User avatar
floresta
 
Posts: 223
Joined: Thu Jul 31, 2008 10:27 am

Re: Blinking without stoping the code.

Post by floresta »

I'm sorry. I don't understand.
Would I place this statement below my initial if statement or inside of it?

if (time_to_change_ledstate(which_led) {
change_led_state(which_led);
set_new_time_to_change(which_led);
}
Don't feel bad, it's what is called pseudo code and it is supposed to make things easier to understand. You can't just paste it into your program but you can use it as a model to construct your own code.

Don

devans
 
Posts: 6
Joined: Thu Feb 17, 2011 10:30 am

Re: Blinking without stoping the code.

Post by devans »

Hi Duffkindt,

I like the sound of your project. Are you controlling relays linked to proper drive way lights?

With all those delays in there your not going to be able to get anything blink so I'm afraid to say you'll need to modify your code a fair bit. For starters I will describe the changes that you'll need to do.

First, Rather than declaring all your pins for your lights as separate variables declare it as a single array variable. (the topPir and bottomPir are fine as is). Having an array will make it a lot easier to set the state of the pins and reduces the size of your code. To declare an array you simply state the type, the variable name followed by square brackets. you can then set the contents of your array in braced brackets. in you case it would be:

Code: Select all

int lightPins[] = {4,5,6,7,8,9,10,11,12};
with your pins for your lights in an array you can now simplify the code in your setup (keeping the topPir and bottomPir as is)

Code: Select all

for (i = 0; i < 9; i = i + 1) {
   pinMode(lightPins[i], OUTPUT)
}
the code above will loop 9 times incrementing i each time. the value of each element in the array will be used to set the pin as output.

now the main loop. What you want to do in here is ensure the loop is free to execute as frequently as possible (Don't use delay as this is in effect pausing the code)

Because it is our aim to have the loop run freely, you will need to firstly add a check if the Arduino is already running a light sequence. to do this add a new boolean variable to keep track of this and then setup your if block. You'll need both an if else (if it is running you need to check if the next light of the sequence is due else you will be checking the state of the PIR's)

in the header:

Code: Select all

boolean seqRunning = false;
in the loop:

Code: Select all

if (seqRunning == TRUE)
{
  // check if sequence need to be moved on
}
else
{
  // check state of PIR's
}
in the else part of your code you will need to add the checks you already have. if either are HIGH then you will enable the sequence and setup the variables used to control it.

Code: Select all

  
// check state of PIR's
if (digitalRead(topPir) == HIGH)//checks topPir condition
{
    seqRunning = TRUE;
    seqDirection = -1;
    seqPosition = 8;
    seqTime = millis();
    seqDelayNextAction = 0;
}
if (digitalRead(bottomPir) == HIGH)//checks bottomPir condition
{
    seqRunning = TRUE;
    seqDirection = +1;
    seqPosition = 0;
    seqTime = millis();
    seqDelayNextAction = 0;
}
a point to note in the above code. If both PIR's are HIGH when the arduino checks this code it will be the code in the bottomPir if statement that will set the variables as it is the last to execute. if you want it to be the other way around then re-arrange the if blocks.

There were also new variables defined:
seqDirection is an int that describes the direction the lights will be lite (positive or negative)
seqPosition is an int which is the pin position in our array of lights that is next to be actioned. it's worth pointing out that we are setting this to either one less or one more than the size of our array. as you will read later we first increment or decrement this position when progressing the sequence. it is also worth noting that because the array structure is 0 based (the first element is accessed as position 0) our seqPosition is set to either 0 (the beginning) or 8 (the end).
seqTime is an unsigned long that captures the current time in ms from when the arduino was last reset
seqDelayNextAction is an int that is used to determine when the next action should occur (in Ms). by setting it to the 0 we are wanting the light sequence to start straight away. if you want the start with a delay then you would add it here.

if for example a sequence is not running and the bottomPir is HIGH then the loop will fall in to the else block and then the setup for the bottomPir. the code will then get to the end of the loop and start again at the top. because the sequence is now running the first condition is true. The next step is to build out the code here to progress the sequence.

first thing to do is to check if an action needs to occur. we have 2 variables that were setup seqTime and seqDelayNextAction to help us determine this.The code to do this is as follows. The code to blink the light would be outside of the if block.

Code: Select all

  //Blink lights goes here... 
  //---

  timeNow = millis();
  if (seqTime + seqDelayNextAction <= timeNow)
  {
     // record the current time as the sequence time for future checks. 
     seqTime = timeNow;

      // Progress Sequence
      //.. 
  }



To progress the sequence we first add the seqDirection to seqPosition. This gives us the new position in our array of lights that will be triggered in the sequence.

After incrementing the seqPosition we need to check that we are still in bounds and haven't got to the end of the sequence.

If still in bound then set the pin to high and setup the delay

Code: Select all

  // Progress Sequence
  seqPosition += seqDirection;
  if (seqPosition>=0 & seqPosition<=8)
  {
       //set the next light in sequence
       digitalWrite(lightPins[seqPosition],HIGH);

       //set the delay until the next sequence cycle 
       if (seqPosition = 0 | seqPosition = 8) //Last lights lite
       {
          seqDelayNextAction = 60000; //All the lights have been lite. wait a minute before turning off
       }
       else
       {
          seqDelayNextAction = 1000; //delay 1 second until next sequence cycle. 
       }
  }
  else //cycle out of bounds. shutdown
  {
    for (i = 0; i < 9; i = i + 1) {
      digitalWrite(lightPins[i],LOW);
    }
  }


The last item of code to tackle is the blinking lights that you would insert where it says //Blink lights goes here...
the logic for this is simple. if the seqDirection is -1 then the topPir intiated the cycle so we want to flash pin 12 else we will flash pin 4. in our array pin 12 is array position 8 and pin 4 is array position 0 , so:

Code: Select all

   //Blink lights goes here...
   Blink=!Blink
   if (seqDirection=-1)
   {
      digitalWrite(lightPins[8],Blink);
   }
   else
   {
      digitalWrite(lightPins[0],Blink);
   }
Blink is a state variable that is declared as a boolean and set to FALSE.
What you will find in the above code is that the state will change quickly..
You will need to create a seperate time control for the blink effect in order to slow it down.

Please bare in mind that whilst this code should work it hasn't been tested as it was written adhoc straight in to forum editor so I'm sure it can be optimised further.. Let me know if you need any further pointers .

s7eve
 
Posts: 2
Joined: Sun Mar 11, 2012 12:14 pm

Re: Blinking without stoping the code.

Post by s7eve »

Hi
I know this is an old thread but im trying to learn about arrays and delay without using delay for a project im working on

Im getting some error, I spend a good 3+ hours going over it and missing something simple. The second one I really dont understand

: In function 'void loop()':
: lvalue required as left operand of assignment
: 'i' was not declared in this scope
: expected `}' at end of input

If anyone as the time to just look over it for me and put me right i would really appreciate it.

Thanks in advance

Code: Select all

nt topPir = 2; //digital input for top pir
int bottomPir = 3; //digital input for bottom pir

int lightPins[] = { 4,5,6,7,8,9,10,11,12};

boolean seqRunning = false;
boolean Blink = false;
int seqDirection = 0;
int seqPosition = 0;
long seqTime = 0;
int  seqDelayNextAction = 0;
long timeNow = 0;


void setup()
{
  for (int i = 0; i <9; i = i + 1){
    pinMode(lightPins[i], OUTPUT);
  }
  pinMode(topPir, INPUT); //declare topPir as input
  pinMode(bottomPir, INPUT); //declare bottomPir as input

}


void loop ()
{
    // check state of PIR's
    if (digitalRead(topPir) == HIGH)//checks topPir condition
    {
//      seqRunning = TRUE;
      seqDirection = -1;
      seqPosition = 8;
      seqTime = millis();
      seqDelayNextAction = 0;
    }
  if (digitalRead(bottomPir) == HIGH)//checks bottomPir condition
  {
//    seqRunning = TRUE;
    seqDirection = +1;
    seqPosition = 0;
    seqTime = millis();
    seqDelayNextAction = 0;
  }

  //Blink lights goes here...
  Blink=!Blink;
   if (seqDirection=-1)
   {
      digitalWrite(lightPins[8],Blink);
   }
   else
   {
      digitalWrite(lightPins[0],Blink);
   }
  
  timeNow = millis();
  if (seqTime + seqDelayNextAction <= timeNow)
  {
    // record the current time as the sequence time for future checks.
    seqTime = timeNow;
 
    // Progress Sequence
  seqPosition += seqDirection;
  
  if (seqPosition>=0 & seqPosition<=8)
  {
       //set the next light in sequence
       digitalWrite(lightPins[seqPosition],HIGH);
  

       //set the delay until the next sequence cycle
       if (seqPosition = 0 | seqPosition = 8) //Last lights lite
       {
          seqDelayNextAction = 60000; //All the lights have been lite. wait a minute before turning off
       }
       else
       {
          seqDelayNextAction = 1000; //delay 1 second until next sequence cycle.
       }
  }
  else //cycle out of bounds. shutdown
  {
    for (i = 0; i < 9; i = i + 1) {
      digitalWrite(lightPins[i],LOW);
    }
  }

    
  } 

User avatar
danmalec
 
Posts: 13
Joined: Fri Nov 18, 2011 3:53 pm

Re: Blinking without stoping the code.

Post by danmalec »

Hi s7eve, the three compiler errors are caused by the following:
lvalue required as left operand of assignment
Caused by:

Code: Select all

if (seqPosition = 0 | seqPosition = 8)
The short answer is that you're using a bitwise OR (single pipe) instead of logical OR (double pipe) and assignment (single equal) instead of comparison (double equal). You probably want:

Code: Select all

if (seqPosition == 0 || seqPosition == 8)
The longer answer for the lvalue error is that it comes down to operator precedence http://en.wikipedia.org/wiki/C_operator ... precedence, with the bitwise OR being evaluated prior to the assignments. So the compiler thinks you're asking to put the value 8 into the result of doing a bitwise OR on 0 and seqPosition.
'i' was not declared in this scope
Caused by:

Code: Select all

for (i = 0; i < 9; i = i + 1) {
You haven't declared a variable i in the global scope or the scope of the loop function, only in the setup function. A quick fix is to do the following:

Code: Select all

for (int i = 0; i < 9; i = i + 1) {
expected `}' at end of input
Looks like the cause is the following block being opened, but never closed.

Code: Select all

if (seqTime + seqDelayNextAction <= timeNow)
  {
You need one more closing brace } at the end of your sketch.

s7eve
 
Posts: 2
Joined: Sun Mar 11, 2012 12:14 pm

Re: Blinking without stoping the code.

Post by s7eve »

Dan

Thank you, think its called looking at this screen for to long, I just couldnt see the this missing bit and as for " if (seqPosition == 0 || seqPosition == 8)" I wouldnt have had a clue so a BIG thank you for your time

Cheers Steve

User avatar
danmalec
 
Posts: 13
Joined: Fri Nov 18, 2011 3:53 pm

Re: Blinking without stoping the code.

Post by danmalec »

Steve

Glad to help; I've been there too - after looking at the same code for a long amount of time, things stop standing out :)

- Dan

User avatar
henry.best
 
Posts: 13
Joined: Sat Mar 03, 2012 9:37 pm

Re: Blinking without stoping the code.

Post by henry.best »

Dan Malec wrote:Steve

Glad to help; I've been there too - after looking at the same code for a long amount of time, things stop standing out :)

- Dan
Agreed. I find that errors in my own code are much harder to find than errors in someone else's code :wink:

diyrmakr
 
Posts: 1
Joined: Mon Nov 12, 2012 5:10 pm

Re: Blinking without stoping the code.

Post by diyrmakr »

Can this array be used to blink 6 leds at six different frequencies?
And if so will it work in micros instead of millis?

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”