Where am I going wrong with the no delay method?

Hi,
I'm just starting out with coding and I've managed to create a simple program that flashes each of the 13 LEDs in order and then back down and loops. The speed of the movement is controlled by a pot on A0.

Here's that code that works:

int led = 2;
int interval = 5; 
int flashDirection = 0;

void setup() {                
  // initialize all of the digital pins as outputs
 for (int i=2; i < 14; i++){
  pinMode(i, OUTPUT);
  }    
}


void loop() {
  for (flashDirection == 0; led != 13; led++) // flash each led from 2 through 13
  {
    flash ();            
  }
  flashDirection = 1; // changeflash direction
  for (flashDirection == 1; led != 2; led--) // flash each led from 13 to 2
  {
    flash ();            
  }
  flashDirection = 0; // change flash direction
}
void flash() {
  interval = analogRead(0)/10; //read pot value, divide by 10 to reduce range of flash sweep speed
  if (interval <5) // delays of less that 5 create too fast of a flash sweep
  {
    interval = 5;
  }
  digitalWrite(led, HIGH);  
  delay(interval);   
  digitalWrite(led, LOW);   
  delay(interval);  
}

Now, I'm trying to get rid of the delay using the example "Blink no delay", but I'm running into trouble. I don't understand enough to figure out why it isn't working. When the code below is run, not a single LED lights up.

int led = 2;
int interval = 5; 
int flashDirection = 0;
long previousMillis = 0;
int ledState = LOW; 

void setup() {                
  // initialize all of the digital pins as outputs
 for (int i=2; i < 14; i++){
  pinMode(i, OUTPUT);
  }    
}

void loop() {
  for (flashDirection == 0; led != 13;) // flash each led from 2 through 13
  {
    flash ();            
  }
  flashDirection = 1; // changeflash direction
  for (flashDirection == 1; led != 2;) // flash each led from 13 to 2
  {
    flash ();            
  }
  flashDirection = 0; // change flash direction
}
void flash() {
  interval = analogRead(0)/10; //read pot value, divide by 10 to reduce range of flash sweep speed
  if (interval <5) // delays of less that 5 create too fast of a flash sweep. Set to minimum of 5
  {
    interval = 5;
  }
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval  && flashDirection == 0){
    previousMillis = currentMillis;
      if (ledState = LOW){
        ledState  = HIGH;
        led ++;}
      else
      ledState = LOW;
      led ++;
  }
    else
    {
      if (ledState = LOW){
        ledState  = HIGH;
        led --;}
      else
      ledState = LOW;
      led --;
    }
      
  digitalWrite(led, ledState);  
}

Is my Boolean expression in the initial flash() if statement wrong? are my if-else statements messed up? I have no idea. Any help would be appreciated.

 for (flashDirection == 0; led != 13;)

Looks like you're missing something...

I see a few problems.
The 'for'-loops, the 'else' and the structure of it all.

What is your goal ? How would you like to use the millis(). Can you explain that ?
Would you like to run loop() repeatedly very fast without any delay, and at the right moment do something with the leds ?
In that case you have to remember the state of the sketch.
You have already the variables to remember that state, with 'led', 'interval' and 'flashDirection', 'previousMillis', and 'ledState'.
Those variables define the complete state.

In the loop function, you don't need any 'for'-loop. You only have to check the variables.
Can you start with a small test ? Blink only led 2 to 13. And another test sketch to make just one led blink using millis(). After that add the direction and the duration and the on/off.

ok, I see that, and instead of using "for" loops, I've changed to "while" since I didn't want to decrement on increment inside that statement.

void loop() {
  while (flashDirection == 0 && led != 13) //  loop until led 13 is flashed
  {
    flash ();            
  }
  flashDirection = 1; // changeflash direction
  while (flashDirection == 1 && led != 2) // loop until led 2 is flashed
  {
    flash ();            
  }
  flashDirection = 0; // change flash direction
}

But still nothing, no LEDs light at all.

Perhaps you would be better served by getting help understanding BlinkWithoutDelay first...
because it's pretty clear that you don't.

No while. Using millis() is acting at a specific time. Can you read my previous post again ? I have changed it after you wrote your previous post.

You can't just put "millis code" in the same place delay() use to be and have it work.

You have to set up a simple state machine to change actions depending on time.

Here are a series of examples that try to explain how to take blink and move it into millis() code. (note that it doesn't account for rollover).
http://www.baldengineer.com/tutorials/multi-tasking-with-arduino/

Here's also a series of examples I made using millis(), you might want to check out the police lights example.

If you use unsigned integers then the only accounting for rollover is that you have a maximum longest interval regardless of when it starts.

Unsigned integer rollover requires no difference in code when you handle it properly in the first place.

if ( Unsigned_Now - Unsigned_Start >= Unsigned_Interval ) {}; // ALWAYS WORKS REGARDLESS OF ROLLOVER

The only times you need "rollover code" is when you don't do the unsigned subtraction or you don't use unsigned math (or manage to klutz it up in some more convoluted way).

in your void flash, instead of

interval = analogRead(0)/10; //read pot value, divide by 10 to reduce range of flash sweep speed
  if (interval <5) // delays of less that 5 create too fast of a flash sweep. Set to minimum of 5
  {
    interval = 5;
  }

you could maybe map the value, like this you can easily control it's min and max values. No need for that if statement.

on your code there are things like this:

if (ledState = LOW)

but i imagine you want

if (ledState == LOW)

== is the comparison operator. it is kind of like "is it equal to?"
= is something different. it is an assignment operator. Makes the left variable equal to the right one.

The idea behind the BlinkWithoutDelay is quite simple, but i remember it also took me some time to understand it.
The basic idea is that for example instead of a delay(100) (which would "pause" the whole Arduino sketch for 100 miliseconds and not allow for anything to happen in this period) we can use the millis() function to see if a predetermind amount of time as gone by.
So the easiest way to change your original sketch (which works for you) would be to just replace those delay() with that millis() technic.

With that first code you posted, the one using delay(), was it actually working like you wanted? Or was it just not giving you any errors?

Well, just a couple of ideas...
:wink:

boguz:
in your void flash, instead of

interval = analogRead(0)/10; //read pot value, divide by 10 to reduce range of flash sweep speed

if (interval <5) // delays of less that 5 create too fast of a flash sweep. Set to minimum of 5
 {
   interval = 5;
 }



you could maybe map the value, like this you can easily control it's min and max values. No need for that if statement.

You do know that min and max use the same basic code if not more?

GoForSmoke:
You do know that min and max use the same basic code if not more?

you think that mapping the value of that analogRead would use more code?
i meant something like this:

int interval = map(analogRead(0), 0, 1023, 5, 255);

the "5" and "255" could easily be replaced by any values he wishes to use as minimum and maximum Interval times.

I wrote an extended demo of the Blink Without Delay concept in the first post in this Thread. It may help to illustrate the technique.

...R

Nick Gammon's explanation includes blocking code and how to avoid it, with example code:

This question comes up practically every day on the Arduino forum - "how do I blink two LEDs at different rates?" or "how do I turn on and off two motors at different times?".

Let's look at an analogy. Say you want to cook breakfast. You need to cook:

Coffee - takes 1 minute
Bacon - takes 2 minutes
Eggs - takes 3 minutes

Now a seasoned cook would NOT do this:

Put coffee on. Stare at watch until 1 minute has elapsed. Pour coffee.
Cook bacon. Stare at watch until 2 minutes have elapsed. Serve bacon.
Fry eggs. Stare at watch until 3 minutes have elapsed. Serve eggs.

The flaw in this is that whichever way you do it, something is going to be cooked too early (and get cold).

In computer terminology this is blocking. That is, you don't do anything else until the one task at hand is over.

What you are likely to do is this:

Start frying eggs. Look at watch and note the time.
Glance at watch from time to time. When one minute is up then ...
Start cooking bacon. Look at watch and note the time.
Glance at watch from time to time. When another minute is up then ...
Put coffee on. Look at watch and note the time.
When 3 minutes are up, everything is cooked. Serve it all up.

In computer terminology this is non-blocking. That is, keep doing other things while you wait for time to be up.