How do I move a sequence through an array?

Hi,

I want to make a specific pattern move through an array for a neopixel type LED project.

For example; I have a pattern of LED brightness represented by an array "5,8,26,9" and I have an LED strip with 100 LEDS.
The full LED strip is represented by a 100 position array. I want to move the pattern along one LED at a time.
So the at first, the LED array would look like... "9,0,0,0,0,0,0,0........."
then "26,9,0,0,0,0,0,0,0........."
8,26,9,0,0,0,0,0,0,0.........
5,8,26,9,0,0,0,0,0,0.........
0,5,8,26,9,0,0,0,0,0.........
0,0,5,8,26,9,0,0,0,0.........
until at the end it would start to loop around again...
.....0,0,0,0,0,0,5,8,26,9
9,0,0,0..........0,0,0,5,8,26
26,9,0,0,0..........0,0,0,5,8

Any suggestions for a good way of doing that?

Setup your pattern in a 100 element array, then output the array starting at index 0. On the next iteration output the array starting at index 1. Keep incrementing the starting point at every iteration until you get to index 99 and then start over. Keep in mind you need to wrap around the end of the array at every iteration. You can use the mod (%) operator to take care of that for you.

Or, output all 0s, and your 4 bytes when you get to the point in the stream where you want them.

In your macro:

#define SIZE (sizeof(Array)/sizeof(Array[0])-1)

for a byte array, it evaluates to;

size = 10 / 1 - 1 = 9

Then in your for loops, you get:

for (j = 0; j < 9; j++) {

which only reads 9 elements (0-8), not 10. The macro you are using gives the number of elements in the array, not the highest index of the array. You would never read the last element…the old off-by-one problem. You should drop the -1 from the macro.

HazardsMind:
Or I could just make them like this.

No, that isn't a good approach. The length and the highest index are different things, and trying to pretend they are the same is a bad idea. Just stick to the length being the number of elements and using an inequality for the upper bound in the for loop and it works fine.

HazardsMind: Your approach puts a bandage on the wound, our approach heals the wound so you don't need the bandage.

HazardsMind:

The length and the highest index are different things,

If the length is 10, and the highest index is always the overall length - 1, then how are they different? Maybe if you have a mixed array of longs, ints and bytes, then yes, it would compromise the functions, but when would that ever really happen?

When will the overall length ever be greater or less than the highest index?

byte foo[10];
Length = 10
Highest index = 9.
10 != 9

HazardsMind:
length - 1 = highest index

Exactly.
As I said, 10 != 9
And as you said, 10 - 1 = 9

I strongly support the method suggested by @DavidOConnor in Reply #1.

Shuffling bytes within the array is nonsense that I would try to avoid even if I was programming on a PC with a high speed CPU and unlimited RAM.

...R

Thankyou. Could you please give me an example of how of use the modulo operator to get the pattern to wrap around.

…example of how of use the modulo operator…

Suppose you want to find out if an integer is odd or even. The modulo operator (%) gives you the remainder after division. Then:

int wholeNumber;
int i;
int remainder;

for (i = 0; i < 30; i++) {
   wholeNumber = i / 2;
   remainder = i % 2;
   Serial.print("wholeNumber = ");   // integer division
   Serial.print(wholeNumber );        // modulo
   Serial.print("    remainder = ");
   Serial.println(remainder);
   if (remainder == 1) {
      Serial.println("Number is odd");
   } else {
      Serial.println("Number is even");
   }
}

If you put this in the setup() function and run it, you will see how modulo is different than division. Because the modulo gives the remainder after division, remainder will alternate between 0 and 1, while wholeNumber increases as the loop progresses. The increase will not be “smooth”, however, since integer division truncates the result.

Thank you. I understand what the modulo does, but I don't understand how it helps to achieve my goal. That is what I was hoping for an example of. It's been ages since I last did some coding and I think the basic math part of my brain has fallen into disrepair!

If you want to read (say) 50 bytes from a 100 byte array starting at byte 75 your code will need to know not to try to read array[100] (which doesn't exist) and use array[0] etc instead.

If you use modulo it will return (say) 98, 99 while the 75-125 count is under 100 and will automatically give 0, 1 2 when the count exceeds 100.

...R

I strongly support the method suggested by @DavidOConnor in Reply #1.

+1

There's almost never a good reason to physically move bytes around in C.


Rob

So this is what I have which is working though I’m not sure it is the most efficient way. Suggestions for improving it are welcome.

// ledStringGREEN[] contains a pattern which is the same length of the LED strip (72 bytes) (actually a short pattern and then trailing zeros)

// PASS RGB DATA TO LED STRING
  for(int ledNo = 0; ledNo < numLEDs; ledNo++) {
     ledString[ledNo].setRGB(0, ledStringGREEN[ledNo], 0);
  }
 
  // ROTATE PATTERN BY 1
  int temp = ledStringGREEN[sequencePosition]; // Store first item in array
  for(int i = numLEDs-1; i >= 0; i--) { 
    ledStringGREEN[i] = ledStringGREEN[i - 1]; // Rotate array   
  } 
  ledStringGREEN[numLEDs] = temp; // Put the first item at the end 
      
  FastLED.show();  // SENDS TO LEDS
  delay(50);
sequencePosition = (sequencePosition + 1) % numLEDs; // increments sequence in loop

I’m thinking a better approach would be one where I could insert short patterns n number of times and move them around the strip independently.