How to move values through an array, slowly / slow progression through a "for loop"

say I have some code like this:

void chasing() {
   for(int i = pixelEnd-1; i > pixelStart; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
  }
  // Fade out the color.  After 8 steps the color should be completely gone.
  leds[pixelStart].r /= 2;
  leds[pixelStart].g /= 2;
  leds[pixelStart].b /= 2;
}

Right now, it works as expected, but the lights chase through really fast, too fast. I'd like to slow it down to a more reasonable speed using timers, the only issue I'm not sure where to put the timer variables?

would something like this work?

void chasing() {
   for(int i = pixelEnd-1; i > pixelStart $ currenttime > timetomovefoward; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
  }
  // Fade out the color.  After 8 steps the color should be completely gone.
  leds[pixelStart].r /= 2;
  leds[pixelStart].g /= 2;
  leds[pixelStart].b /= 2;
}

would something like this work?

No. The for loop would iterate just as fast, if it iterated at all.

You must completely rethink how you write a program if you wish to avoid the dreaded delay() function. That means NO for loops.

Not to delve into the code too much but seem to me you need something along these lines (pseudo-ish code):

int current_i = *123* //some starting, larger number that is going to decrease

void loop() //the main loop (or some other loop)
}

  if (*xyz*)     //see the "blink without delay" example-> the "timer" part, or more precisely time based part
   {

    *abc*   //do your code, using the current_i

    temporary_i = current_i - 1  //this part will decrease current_i for 1 or a specified amount
    current_i = temporary_i  //remember the new current_i
   {


}

//and then the code repeats depending on the time interval you choose

I'm not 100% sure this is what you need, but might be worth looking into it.

I was gonna ask paul for some advice.... your example gives me some ideas, but I think I would still need some for loops to use that.

The value for each address of the LED strip is stored in an array, which I've divided into four zones that need to be able to be controlled separately.

ideally, I'd like to be able to change the zone size easily without having to change all my functions, but that is not a requirement.

What you need is something like this (Pseudo code):

for(int i = pixelEnd-1; i > pixelStart; i-- ) {
change your LEDs;
wait a while;
}

For wait a while, see the 'blink without delay' example, either in the learning pages of this site or in the IDE.

is that blocking? meaning, that if the sketch is in the for loop “waiting” can nothing else happen?

See reply #1 on this page: http://gammon.com.au/blink

(And read the whole page too).

Thanks Nick, I’ve just got a chance to skim through it. BTW, bacon takes way longer to cook that two minutes, unless your talking about the microwavable kind :frowning:

Nick,

I have taken a look at your examples now and i have a few questions.

In the LedFlasher.cpp file, I see you have a few functions LedFlasher::on, LedFlasher::off, and LedFlasher::update.

The on and off functions are only there to allow people to turn of the led’s manually, without the timing correct? So the code i’d be interested in would be the update part of the class?

If that is true, then if i take a look at the update code,

void LedFlasher::update ()
  {
  // do nothing if not active
  if (!active_)
    return;
    
  unsigned long now = millis ();
  // if time to do something, do it
  if (now - startTime_ >= currentInterval_)
    {
    if (digitalRead (pin_) == LOW)
      {
      digitalWrite(pin_, HIGH);
      currentInterval_ = timeOn_;  
      }
    else
      {
      digitalWrite(pin_, LOW);
      currentInterval_ = timeOff_;  
      }
    startTime_ = now;  
    } // end of if
  
  } // end of LedFlasher::update

I’m using this with LED strips, so instead of “digitalWrite” i’d substitute the color levels. The LED strip is represented as an array, so if i wrote something like

 for(int i = pixelStart; i < pixelEnd; i++) {
    update(i);
  }

then modified your code

int LedFlasher::update (int pixel)
  {
  // do nothing if not active
  if (!active_)
    return;
    
  unsigned long now = millis ();
  // if time to do something, do it
  if (now - startTime_ >= currentInterval_)
    {
      leds[pixel].r = leds[pixel - 1].r 
      currentInterval_ = timeOn_;  
      }
    else
      {
      leds[pixel].r = leds[pixel - 1].r 
      currentInterval_ = timeOff_;  
      }
    startTime_ = now;  
    } // end of if
  
  } // end of LedFlasher::update

and that would chase “red” lights on my strip at a interval, assuming i defined the intervals? I will of course try it now, but I would like to know if this is the right track, or if there is a better way?

Qdeathstar: The on and off functions are only there to allow people to turn of the led's manually, without the timing correct? So the code i'd be interested in would be the update part of the class?

The "on" function activates it. So for the example case for the guy I wrote it for, he was doing an Enterprise with LEDs down the side. If you were opening an external door, you might want LEDs flashing around that door at 1 second intervals, while the door was open. So the "on" is for saying "the door is open".

For LED strips you might want something simpler. I seem to recall a sketch a while back for using with a shift register:

http://www.gammon.com.au/forum/?id=11518

(See further down the page, for example at the part where it rotates LEDs).

How many LEDs do you have? You basically want a "current state" (ie. which ones are on) and when a certain number of milliseconds elapses, update that (rotate or shift them) and then output the new setting to the digital ports.

It can be easier just to write from scratch. Here is a simple sketch that just scrolls a pattern across some LEDs:

const int pins [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };

// number of items in an array
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

const unsigned long INTERVAL = 200;

unsigned long pattern = 0b00000110011;

void setup ()
  {
  for (byte i = 0; i < ARRAY_SIZE (pins); i++)
    pinMode (pins [i], OUTPUT);
  }  // end of setup

unsigned long lastUpdate;

void loop ()
  {
  // too soon? Do nothing
  if (millis () - lastUpdate < INTERVAL)
    return;
  
  lastUpdate = millis ();
 
  // check if low-order bit is currently set
  byte oldLowBit = pattern & 1;
  
  // shift pattern across
  pattern >>= 1;

  // rotate in from right
  if (oldLowBit)
    pattern |= bit (ARRAY_SIZE (pins));
  
  // display new results
  for (byte i = 0; i < ARRAY_SIZE (pins); i++)
    {
    if (pattern & bit (i))
      digitalWrite (pins [i], HIGH);
    else  
      digitalWrite (pins [i], LOW);
    }  // end of for loop
  
  }  // end of loop

Now turn the active part into a couple of functions, pass in which pins you want and how long to wait for, and the whole thing could handle groups of LEDs.

I don’t think i can use digitalWrite (pins , HIGH);
because the LEDs i’m controlling are actually lpd6803 strips, connected via SPI. I’m using the Fast_LED library, and in order to control the lights, you do something like:
* *leds[controller number].r = 255; leds[controller number].g = 255; leds[controller number].b = 255;* *
then, if you had 50 pixels for each zone, you have to tell the SPI what the color is for those 50 pixels, (which i had been doing in a for loop, so i don’t have to write 50 of the above code.
I tried something like i had suggested, but it doesn’t seem to move past the first controller"
```
*int chasingUpdate(int pixel) {
  unsigned long currentInterval = 1000;
  unsigned long now = millis ();
  // if time to do something, do it
  Serial.println(pixel);
  Serial.println(“and”);
  if (now - chasingStartTime >= currentInterval)
    {
    leds[pixel].r = leds[pixel - 1 ].r;
    leds[pixel].b = leds[pixel - 1].b;
    leds[pixel].g = leds[pixel - 1].g;
    Serial.println(pixel);
    Serial.println(“and”);
    Serial.println(pixel - 1);
    chasingStartTime = now; 
    } // end of if
}

void chasing() {
  leds[pixelStart].r = 255;
  leds[pixelStart].g = 0;
  leds[pixelStart].b = 125;
  for(int i = pixelStart; i < pixelEnd; i++) {
    chasingUpdate(i);
}
}*
```
the lights stay on for 1 second, then blink, but it doens’t advance down the line like i would expect it too…
_6803_LED_box1.ino (16.5 KB)

My link above used SPI for the 595 chips controlling the LEDs.

I can’t see any SPI in your recent post. More information is needed.

Instead of this

  for(int i = pixelEnd-1; i > pixelStart; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
  }

Couldn't you just have this

  for(int i = pixelEnd-1; i > pixelStart; i-- ) 
      leds[i] = leds[i-1];

Oops, sorry, you're trying to slow it down :(

I'm using the older version of the fast led library...

@Nick,

I am using a library that handles writing to SPI and converting the color information into bits for me. http://code.google.com/p/fastspi/

I started looking for where/how to write to the spi pins directly, and found the data sheet for the lpd 6803 lights I am driving http://pdf.datasheetarchive.com/indexerfiles/Datasheets-UD1/DSAUD00854.pdf

Basic timing sequence A. First shift in 32bit “0” as start frame, then shift in all data frame, start frame and data frame both are shift by high-bit, every data is input on DCLK rising edge. B. The first data frame is corresponding LED light nearest from shift-in polar, its format includes 1bit as start “1” plus 3 groups 5bits grey level. C. Turn shift in all data, add append pulse of corresponding point, new data start valid.

unfortunately I can't make a whole lot of sense from that.

this talks about 32 bit and 16 bit, but the colors for a 6803 are 15 bit....

just a small bump, if anyone can understand what that data sheet is talking about, I'd like too aswell.

I was hoping to see all your code. Still hoping for that.

Qdeathstar: Basic timing sequence A. First shift in 32bit “0” as start frame, then shift in all data frame, start frame and data frame both are shift by high-bit, every data is input on DCLK rising edge. B. The first data frame is corresponding LED light nearest from shift-in polar, its format includes 1bit as start “1” plus 3 groups 5bits grey level. C. Turn shift in all data, add append pulse of corresponding point, new data start valid.

Looks like you are sending groups of 16 bits (ie. two bytes). First one is all zeros. From then on 3 x 5 (15) bits with a 1 bit to wrap up the 16 bits.

So, something like:

SPI.transfer (0);  // start of frame
SPI.transfer (0);
SPI.transfer (0xFF);  // white
SPI.transfer (0xFF);
// and so on for other bytes

the strips have two pins, on for data (which I assume that is what your post describes>, and then clock.. does clock go out automatically? also, how do does the strip know which led to show the data that is sent on? or how many leds there are total?

is it that you write the fifteen bit colors, one for each light, and it starts filling from the first led onwards until it gets the zero byte again?

The nature of SPI is that the processor will send clock (SCK) and data (MOSI) simultaneously as appropriate. Some SPI interfaces have SS (slave select) but it can be omitted if we assume the slave is selected (as we would for the LED strip) and some may have MISO (master in) if the device sends data back to the master. Again, an LED strip wouldn't need that. So an LED strip will typically have 4 wires: power, Gnd, SCK, MOSI.

http://www.gammon.com.au/spi

Therefore generally what you have to do is send out enough bytes to fill the strip up, so if it takes 2 bytes for one colour (3 x RGB) and you have 100 LEDs then I would expect you to send out 200 bytes. At 8 MHz clocking rate this is still pretty fast (25 µS).

Which strip is it? The ones sold by Adafruit, for example, come with demo libraries which do all the hard work.