How to "shift a 1D array"?

Im doing some stuff with LED’s and ports. I have an array:

int ledpins[] = {1,2,3,4};

I have a for loop that increments and puts out current to each of 4 led’s in turn:

for (int i = 0; i < 4; i++) {
    int count = 0;
  
  while (count <= 300) {
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[i], HIGH);
  delay(delaytime);
  wipeTotal();
  
  digitalWrite(groundpins[1], HIGH);
  digitalWrite(ledpins[i+2], HIGH);
  delay(delaytime);
  wipeTotal();
  count++;
  }
  }

Im doing POV with a 2x2x2 LED cube. Here’s the thing:

when I get to this part of the code

digitalWrite(ledpins[i+2], HIGH);

the led’s 0 and 1 don’t light up on the bottom (because the code says to do i +2, and there is no pin 4 or 5 connected to anything).

How do I get the code to loop back to ledpins[0] once it reaches ledpins[3]?

thanks!

Modulus. The modulus operator is %

  digitalWrite(ledpins[(i+2) % 4], HIGH);

Modulus is "the remainder after the value is divided by the modulus value", so 6 / 4 = 1 remainder 2, so 6 % 4 = 2.

Thanks! It works now!

I was also wondering, how could I get 2d arrays working on this 2x2x2 cube?

Like this:

Layer 1:

1 0
0 0

Layer 2:

0 0
0 1

and then I could pass both to the loop, and it would show those LED's on?

By using 3d arrays, not 2d arrays?

unsigned char ledpins[][] = {
  {1, 2, 3, 4},
  {5, 6, 7, 8}
};

digitalWrite(ledpins[1][3], HIGH); // Layer 1 (zero based), pin 3 (zero based)

I fear that might not work.

What I have here is 2 layers of LED's, 4 on each layer. The anodes of each layer are soldered together and put into a single port (layer 1 is port 12, layer 2 is port 13).

Each column of LED's cathodes are soldered together, so they are pins 1 to 4. I need the POV thing to display certain stuff, but I can do that now.

What Im wondering is how can I make arrays for each layer, and then write the engine to translate that to the cube.

Two separate 4 element arrays? Or one 8 element array, and use 0-3 for one layer, and 4-7 for the other?

(i+2)%4 for one, and ((i+2)%4) + 4

Here’s the code just so it makes a bit more sense:

/*Code provided by Brian W. Cordes 2013*/

int ledpins[] = {1,2,3,4};
int groundpins[] = {12,13};
void setup ()
{
  for(int i = 0; i < 4; i++)
  {        
      pinMode(ledpins[i],OUTPUT); 
  }                          
  for (int i= 0; i<2; i++)
  {pinMode(groundpins[i],OUTPUT);}

}

void loop()
{
 twist();
 drop();
 diagonal();
}

void twist()
{
  int delaytime=100;
   digitalWrite(groundpins[0], HIGH);
    delay(100);   
  digitalWrite(ledpins[0], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[1], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[2], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[3], HIGH);
  delay(delaytime);
  
   digitalWrite(ledpins[0], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[1], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[2], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[3], LOW);  
 delay(delaytime);
 digitalWrite(groundpins[0], LOW);
 
 
 
 
 digitalWrite(groundpins[1], HIGH);
    delay(100);   
  digitalWrite(ledpins[1], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[2], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[3], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[0], HIGH);
  delay(delaytime);
  
   digitalWrite(ledpins[1], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[2], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[3], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[0], LOW);  
  delay(delaytime);
  digitalWrite(groundpins[1], LOW);
  
  
  digitalWrite(groundpins[0], HIGH);
    delay(100);   
  digitalWrite(ledpins[2], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[3], HIGH);  
  delay(delaytime);               
  digitalWrite(ledpins[0], HIGH); 
  delay(delaytime);                
  digitalWrite(ledpins[1], HIGH);
  delay(delaytime);
  
  digitalWrite(ledpins[2], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[3], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[0], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[1], LOW);  
  delay(delaytime);
  digitalWrite(groundpins[0], LOW);
  
  digitalWrite(groundpins[1], HIGH);
    delay(100);   
  digitalWrite(ledpins[3], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[0], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[1], HIGH);  
  delay(delaytime);                
  digitalWrite(ledpins[2], HIGH);
  delay(delaytime);
  
  digitalWrite(ledpins[3], LOW);  
  delay(delaytime);               
  digitalWrite(ledpins[0], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[1], LOW);  
  delay(delaytime);                
  digitalWrite(ledpins[2], LOW);  
  delay(delaytime);
  digitalWrite(groundpins[1], LOW);
}

void drop()
{
  int dtime = 75;
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[0], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1],HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[0], LOW);
  
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[1], LOW);
  
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[2], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[2], LOW);
  
   digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[3], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[3], LOW);
  
  
  //second time down
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[0], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1],HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[0], LOW);
  
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[1], LOW);
  
  digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[2], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[2], LOW);
  
   digitalWrite(groundpins[0], HIGH);
  digitalWrite(ledpins[3], HIGH);
  delay(dtime);
  digitalWrite(groundpins[0], LOW);
  digitalWrite(groundpins[1], HIGH);
  delay(dtime);
  digitalWrite(groundpins[1], LOW);
  digitalWrite(ledpins[3], LOW);
  
  
}
 
void diagonal()
{
 int dtime= 100;
 //bottom pin 0 on
 digitalWrite(groundpins[1], HIGH);
 digitalWrite(ledpins[0], HIGH);
 delay(dtime);
 //bottom pin 0 off
 digitalWrite(groundpins[1], LOW);
 digitalWrite(ledpins[0], LOW);
 delay(dtime);
 //top pin 1 on
 digitalWrite(groundpins[0], HIGH);
 digitalWrite(ledpins[1], HIGH);
 delay(dtime);
 //top pin 1 off
 digitalWrite(groundpins[0], LOW);
 digitalWrite(ledpins[1], LOW);
 //bottom pin 2 on
 digitalWrite(groundpins[1], HIGH);
 digitalWrite(ledpins[2], HIGH);
 delay(dtime);
 //bottom pin 2 off
 digitalWrite(groundpins[1], LOW);
 digitalWrite(ledpins[2], LOW);
  //top pin 3 on
 digitalWrite(groundpins[0], HIGH);
 digitalWrite(ledpins[3], HIGH);
 delay(dtime);
 //top pin 3 off
 digitalWrite(groundpins[0], LOW);
 digitalWrite(ledpins[3], LOW);
 
 
 
 
 
 //top pin 0 on
 digitalWrite(groundpins[0], HIGH);
 digitalWrite(ledpins[0], HIGH);
 delay(dtime);
 //top pin 0 off
 digitalWrite(groundpins[0], LOW);
 digitalWrite(ledpins[0], LOW);
 delay(dtime);
 //bottom pin 1 on
 digitalWrite(groundpins[1], HIGH);
 digitalWrite(ledpins[1], HIGH);
 delay(dtime);
 //bottom pin 1 off
 digitalWrite(groundpins[1], LOW);
 digitalWrite(ledpins[1], LOW);
 //top pin 2 on
 digitalWrite(groundpins[0], HIGH);
 digitalWrite(ledpins[2], HIGH);
 delay(dtime);
 //top pin 2 off
 digitalWrite(groundpins[0], LOW);
 digitalWrite(ledpins[2], LOW);
  //bottom pin 3 on
 digitalWrite(groundpins[1], HIGH);
 digitalWrite(ledpins[3], HIGH);
 delay(dtime);
 //bottom pin 3 off
 digitalWrite(groundpins[1], LOW);
 digitalWrite(ledpins[3], LOW);
 
 };

its 2 seperate layers, but they share the pins 1-4.

You don’t really need an array anyway. Not for the patterns. You have 8 LEDs. What else around here has that magic number 8? Oh, I know - a byte.

Why not have just a single byte representing each pattern you want to use, and examine the bits within that byte? You can have an array for the LED pin numbers if you like:

unsigned char cathodes[] = {1, 2, 3, 4};
unsigned char anodes[] = {12, 13};

unsigned char layer = 0;
unsigned char pattern = 0;

void display() {
  digitalWrite(anodes[layer], LOW); // Turn off last layer
  layer++;
  unsigned char bits = pattern >> (4 * layer); // Select the bits for this layer
  for (int i = 0; i < 4; i++) {
    digitalWrite(cathodes[i], bits & (1<<i) ? LOW : HIGH); // Bit of 1 gives LOW, 0 gives HIGH
  }
  digitalWrite(anodes[layer], HIGH);
}

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(cathodes[i], OUTPUT);
    digitalWrite(cathodes[i], HIGH);
  }
  for (int i = 0; i < 2; i++) {
    pinMode(anodes[i], OUTPUT);
    pinMode(anodes[i], LOW);
  }
}

void loop() {
  static unsigned long displayTimer = millis();
  static unsigned long animTimer = millis();
  unsigned long now = millis();

  if (now - displayTimer > 0) {
    display();
  }

  if (now - animTimer >= 500) {
    pattern++;
  }
}

I haven’t tested that code (it compiles, but I haven’t got your LED setup to try it), but theoretically it should give each layer 1ms of display time, and display the contents of the 8-bit value “pattern”. Pattern increments every 500 milliseconds to give you a display of binary numbers.

:( doesn't work.

Im checking it though, seeing what may be up...

What Im wondering, could I do this:

A byte is 8 bits, a nibble is 4 bits (half a byte).

so for this instance, I could theoretically reverse engineer two 2D arrays to form the byte?

like this:

Array 1:

1 0
0 1

Array 2:

0 1
1 0

Which would translate to:

nib1(1001) :: nib2(0110)

which would be this:

byte(10010110)

is this possible?

Im trying to get the arrays because it will be INFINITELY easier to program images and stuff to the cube instead of having to rewrite the code from scratch for each pattern.

I’ve just rigged up a little test circuit and ironed out a couple of bugs. Try this version:

unsigned char cathodes[4] = {1, 2, 3, 4};
unsigned char anodes[2] = {12, 13};

unsigned char layer = 0;
unsigned char pattern = 0;

void display() {
  digitalWrite(anodes[layer], LOW); // Turn off last layer
  layer = (layer + 1) % 2;
  unsigned char bits = pattern >> (4 * layer); // Select the bits for this layer
  for (int i = 0; i < 4; i++) {
    digitalWrite(cathodes[i], (bits & (1<<i)) ? LOW : HIGH); // Bit of 1 gives LOW, 0 gives HIGH
  }
  digitalWrite(anodes[layer], HIGH);
}

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(cathodes[i], OUTPUT);
    digitalWrite(cathodes[i], HIGH);
  }
  for (int i = 0; i < 2; i++) {
    pinMode(anodes[i], OUTPUT);
    digitalWrite(anodes[i], LOW);
  }
}

void loop() {
  static unsigned long displayTimer = millis();
  static unsigned long animTimer = millis();
  unsigned long now = millis();

  if (now - displayTimer > 0) {
    displayTimer = now;
    display();
  }

  if (now - animTimer >= 100) {
    animTimer = now;
    pattern++;
  }
}

My test rig is common cathode, so I have had to invert the signals and hope :wink:

Using this code you just set the variable pattern to be whatever pattern you like, yes, made up of two nibbles - the lower nibble is layer 1, the upper nibble is layer 2.

Even better would be to use a timer configured to trigger the display function from its interrupt (check out the TimerOne library), then you are free to just change the pattern variable at any time to change the display. (http://playground.arduino.cc/code/timer1)

Incorporating Timer1 it becomes simpler:

#include <TimerOne.h>

const unsigned char cathodes[4] = {1, 2, 3, 4};
const unsigned char anodes[2] = {12, 13};

volatile unsigned char pattern = 0;

void display() {
  static unsigned char layer = 0;
  digitalWrite(anodes[layer], LOW); // Turn off last layer
  layer = (layer + 1) % 2;
  unsigned char bits = pattern >> (4 * layer); // Select the bits for this layer
  for (int i = 0; i < 4; i++) {
    digitalWrite(cathodes[i], (bits & (1<<i)) ? LOW : HIGH); // Bit of 1 gives LOW, 0 gives HIGH
  }
  digitalWrite(anodes[layer], HIGH);
}

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(cathodes[i], OUTPUT);
    digitalWrite(cathodes[i], HIGH);
  }
  for (int i = 0; i < 2; i++) {
    pinMode(anodes[i], OUTPUT);
    digitalWrite(anodes[i], LOW);
  }
  Timer1.initialize(10000);
  Timer1.attachInterrupt(display);
}

void loop() {
  delay(100);
  pattern++;
}

That’s set to a 100Hz timer (50Hz refresh rate), and you can see now how the loop() is completely freed up for you to do what you want in - the whole of the displaying is taken care of for you by the timer. Just set pattern to be the pattern of LEDs you want on, and it displays it instantly. You can now build up an array of patterns, such as:

const unsigned char chaser[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

and run it:

void loop() {
  for (int i = 0; i < 8; i++) {
    pattern = chaser[i];
    delay(100);
  }
}