Electronic – arduino – Code for ripple effect of an 8x8x8 LED cube Arduino

arduinoprogramming

I want to code the ripple effect animation as seen in the first 7 seconds of this video.

This is how my code works now. It uses 9 shift registers(74HC595); 8 for the 64 columns and 1 for the 8 layers.

How should I do this? I barely understand the code below. It draws an expanding cube.

/* Voxel Shield Sketch
  Controls a Light Emitting Diode(LED) Cube of 8x8x8 voxels arranged
  by 64 columns(anodes) and 8 layers(cathodes).
*/

byte cube[][8] = {
  // Layer 1
  {0b00000000,  // Row 1
   0b00000000,  // Row 2
   0b00000000,  // Row 3
   0b00000000,  // Row 4
   0b00000000,  // Row 5
   0b00000000,  // Row 6
   0b00000000,  // Row 7
   0b00000000}, // Row 8

  // Layer 2
  {0b00000000,  // Row 1
   0b00000000,  // Etc ...
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 3
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 4
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 5 
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 6
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 7
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000},

  // Layer 8
  {0b00000000, 
   0b00000000, 
   0b00000000, 
   0b00000000,
   0b00000000,
   0b00000000, 
   0b00000000, 
   0b00000000}
};
// Shift Register pin assignments
int dataPin     = 2;
int clockPin    = 3;
int latchPin    = 5;
int masterClear = 4;

// Cube indicies
int rowIndex   = 0;        // used for shifting out the data
int layerIndex  = 0;

void all(){
  cube[0][0] = 255; cube[1][0] = 255; cube[2][0] = 255; cube[3][0] = 255; cube[4][0] = 255; cube[5][0] = 255; cube[6][0] = 255; cube[7][0] = 255; 
  cube[0][1] = 255; cube[1][1] = 255; cube[2][1] = 255; cube[3][1] = 255; cube[4][1] = 255; cube[5][1] = 255; cube[6][1] = 255; cube[7][1] = 255; 
  cube[0][2] = 255; cube[1][2] = 255; cube[2][2] = 255; cube[3][2] = 255; cube[4][2] = 255; cube[5][2] = 255; cube[6][2] = 255; cube[7][2] = 255; 
  cube[0][3] = 255; cube[1][3] = 255; cube[2][3] = 255; cube[3][3] = 255; cube[4][3] = 255; cube[5][3] = 255; cube[6][3] = 255; cube[7][3] = 255; 
  cube[0][4] = 255; cube[1][4] = 255; cube[2][4] = 255; cube[3][4] = 255; cube[4][4] = 255; cube[5][4] = 255; cube[6][4] = 255; cube[7][4] = 255; 
  cube[0][5] = 255; cube[1][5] = 255; cube[2][5] = 255; cube[3][5] = 255; cube[4][5] = 255; cube[5][5] = 255; cube[6][5] = 255; cube[7][5] = 255; 
  cube[0][6] = 255; cube[1][6] = 255; cube[2][6] = 255; cube[3][6] = 255; cube[4][6] = 255; cube[5][6] = 255; cube[6][6] = 255; cube[7][6] = 255; 
  cube[0][7] = 255; cube[1][7] = 255; cube[2][7] = 255; cube[3][7] = 255; cube[4][7] = 255; cube[5][7] = 255; cube[6][7] = 255; cube[7][7] = 255; 
}
void none(){
  cube[0][0] = 0; cube[1][0] = 0; cube[2][0] = 0; cube[3][0] = 0; cube[4][0] = 0; cube[5][0] = 0; cube[6][0] = 0; cube[7][0] = 0; 
  cube[0][1] = 0; cube[1][1] = 0; cube[2][1] = 0; cube[3][1] = 0; cube[4][1] = 0; cube[5][1] = 0; cube[6][1] = 0; cube[7][1] = 0; 
  cube[0][2] = 0; cube[1][2] = 0; cube[2][2] = 0; cube[3][2] = 0; cube[4][2] = 0; cube[5][2] = 0; cube[6][2] = 0; cube[7][2] = 0; 
  cube[0][3] = 0; cube[1][3] = 0; cube[2][3] = 0; cube[3][3] = 0; cube[4][3] = 0; cube[5][3] = 0; cube[6][3] = 0; cube[7][3] = 0; 
  cube[0][4] = 0; cube[1][4] = 0; cube[2][4] = 0; cube[3][4] = 0; cube[4][4] = 0; cube[5][4] = 0; cube[6][4] = 0; cube[7][4] = 0; 
  cube[0][5] = 0; cube[1][5] = 0; cube[2][5] = 0; cube[3][5] = 0; cube[4][5] = 0; cube[5][5] = 0; cube[6][5] = 0; cube[7][5] = 0; 
  cube[0][6] = 0; cube[1][6] = 0; cube[2][6] = 0; cube[3][6] = 0; cube[4][6] = 0; cube[5][6] = 0; cube[6][6] = 0; cube[7][6] = 0; 
  cube[0][7] = 0; cube[1][7] = 0; cube[2][7] = 0; cube[3][7] = 0; cube[4][7] = 0; cube[5][7] = 0; cube[6][7] = 0; cube[7][7] = 0; 
}
void box(){
  cube[0][0] = 0b11111111; cube[1][0] = 0b10000001; cube[2][0] = 0b10000001; cube[3][0] = 0b10000001; cube[4][0] = 0b10000001; cube[5][0] = 0b10000001; cube[6][0] = 0b10000001; cube[7][0] = 0b11111111; 
  cube[0][1] = 0b10000001; cube[1][1] = 0b00000000; cube[2][1] = 0b00000000; cube[3][1] = 0b00000000; cube[4][1] = 0b00000000; cube[5][1] = 0b00000000; cube[6][1] = 0b00000000; cube[7][1] = 0b10000001; 
  cube[0][2] = 0b10000001; cube[1][2] = 0b00000000; cube[2][2] = 0b00000000; cube[3][2] = 0b00000000; cube[4][2] = 0b00000000; cube[5][2] = 0b00000000; cube[6][2] = 0b00000000; cube[7][2] = 0b10000001; 
  cube[0][3] = 0b10000001; cube[1][3] = 0b00000000; cube[2][3] = 0b00000000; cube[3][3] = 0b00000000; cube[4][3] = 0b00000000; cube[5][3] = 0b00000000; cube[6][3] = 0b00000000; cube[7][3] = 0b10000001; 
  cube[0][4] = 0b10000001; cube[1][4] = 0b00000000; cube[2][4] = 0b00000000; cube[3][4] = 0b00000000; cube[4][4] = 0b00000000; cube[5][4] = 0b00000000; cube[6][4] = 0b00000000; cube[7][4] = 0b10000001; 
  cube[0][5] = 0b10000001; cube[1][5] = 0b00000000; cube[2][5] = 0b00000000; cube[3][5] = 0b00000000; cube[4][5] = 0b00000000; cube[5][5] = 0b00000000; cube[6][5] = 0b00000000; cube[7][5] = 0b10000001; 
  cube[0][6] = 0b10000001; cube[1][6] = 0b00000000; cube[2][6] = 0b00000000; cube[3][6] = 0b00000000; cube[4][6] = 0b00000000; cube[5][6] = 0b00000000; cube[6][6] = 0b00000000; cube[7][6] = 0b10000001; 
  cube[0][7] = 0b11111111; cube[1][7] = 0b10000001; cube[2][7] = 0b10000001; cube[3][7] = 0b10000001; cube[4][7] = 0b10000001; cube[5][7] = 0b10000001; cube[6][7] = 0b10000001; cube[7][7] = 0b11111111;
}
void box2(){
  cube[0][0] = 0b00000000; cube[1][0] = 0b00000000; cube[2][0] = 0b00000000; cube[3][0] = 0b00000000; cube[4][0] = 0b00000000; cube[5][0] = 0b00000000; cube[6][0] = 0b00000000; cube[7][0] = 0b00000000; 
  cube[0][1] = 0b00000000; cube[1][1] = 0b01111110; cube[2][1] = 0b01000010; cube[3][1] = 0b01000010; cube[4][1] = 0b01000010; cube[5][1] = 0b01000010; cube[6][1] = 0b01111110; cube[7][1] = 0b00000000; 
  cube[0][2] = 0b00000000; cube[1][2] = 0b01000010; cube[2][2] = 0b00000000; cube[3][2] = 0b00000000; cube[4][2] = 0b00000000; cube[5][2] = 0b00000000; cube[6][2] = 0b01000010; cube[7][2] = 0b00000000; 
  cube[0][3] = 0b00000000; cube[1][3] = 0b01000010; cube[2][3] = 0b00000000; cube[3][3] = 0b00000000; cube[4][3] = 0b00000000; cube[5][3] = 0b00000000; cube[6][3] = 0b01000010; cube[7][3] = 0b00000000; 
  cube[0][4] = 0b00000000; cube[1][4] = 0b01000010; cube[2][4] = 0b00000000; cube[3][4] = 0b00000000; cube[4][4] = 0b00000000; cube[5][4] = 0b00000000; cube[6][4] = 0b01000010; cube[7][4] = 0b00000000; 
  cube[0][5] = 0b00000000; cube[1][5] = 0b01000010; cube[2][5] = 0b00000000; cube[3][5] = 0b00000000; cube[4][5] = 0b00000000; cube[5][5] = 0b00000000; cube[6][5] = 0b01000010; cube[7][5] = 0b00000000; 
  cube[0][6] = 0b00000000; cube[1][6] = 0b01111110; cube[2][6] = 0b01000010; cube[3][6] = 0b01000010; cube[4][6] = 0b01000010; cube[5][6] = 0b01000010; cube[6][6] = 0b01111110; cube[7][6] = 0b00000000; 
  cube[0][7] = 0b00000000; cube[1][7] = 0b00000000; cube[2][7] = 0b00000000; cube[3][7] = 0b00000000; cube[4][7] = 0b00000000; cube[5][7] = 0b00000000; cube[6][7] = 0b00000000; cube[7][7] = 0b00000000;
}
void box3(){
  cube[0][0] = 0b00000000; cube[1][0] = 0b00000000; cube[2][0] = 0b00000000; cube[3][0] = 0b00000000; cube[4][0] = 0b00000000; cube[5][0] = 0b00000000; cube[6][0] = 0b00000000; cube[7][0] = 0b00000000; 
  cube[0][1] = 0b00000000; cube[1][1] = 0b00000000; cube[2][1] = 0b00000000; cube[3][1] = 0b00000000; cube[4][1] = 0b00000000; cube[5][1] = 0b00000000; cube[6][1] = 0b00000000; cube[7][1] = 0b00000000; 
  cube[0][2] = 0b00000000; cube[1][2] = 0b00000000; cube[2][2] = 0b00111100; cube[3][2] = 0b00100100; cube[4][2] = 0b00100100; cube[5][2] = 0b00111100; cube[6][2] = 0b00000000; cube[7][2] = 0b00000000; 
  cube[0][3] = 0b00000000; cube[1][3] = 0b00000000; cube[2][3] = 0b00100100; cube[3][3] = 0b00000000; cube[4][3] = 0b00000000; cube[5][3] = 0b00100100; cube[6][3] = 0b00000000; cube[7][3] = 0b00000000; 
  cube[0][4] = 0b00000000; cube[1][4] = 0b00000000; cube[2][4] = 0b00100100; cube[3][4] = 0b00000000; cube[4][4] = 0b00000000; cube[5][4] = 0b00100100; cube[6][4] = 0b00000000; cube[7][4] = 0b00000000; 
  cube[0][5] = 0b00000000; cube[1][5] = 0b00000000; cube[2][5] = 0b00111100; cube[3][5] = 0b00100100; cube[4][5] = 0b00100100; cube[5][5] = 0b00111100; cube[6][5] = 0b00000000; cube[7][5] = 0b00000000; 
  cube[0][6] = 0b00000000; cube[1][6] = 0b00000000; cube[2][6] = 0b00000000; cube[3][6] = 0b00000000; cube[4][6] = 0b00000000; cube[5][6] = 0b00000000; cube[6][6] = 0b00000000; cube[7][6] = 0b00000000; 
  cube[0][7] = 0b00000000; cube[1][7] = 0b00000000; cube[2][7] = 0b00000000; cube[3][7] = 0b00000000; cube[4][7] = 0b00000000; cube[5][7] = 0b00000000; cube[6][7] = 0b00000000; cube[7][7] = 0b00000000;
}
void box4(){
  cube[0][0] = 0b00000000; cube[1][0] = 0b00000000; cube[2][0] = 0b00000000; cube[3][0] = 0b00000000; cube[4][0] = 0b00000000; cube[5][0] = 0b00000000; cube[6][0] = 0b00000000; cube[7][0] = 0b00000000; 
  cube[0][1] = 0b00000000; cube[1][1] = 0b00000000; cube[2][1] = 0b00000000; cube[3][1] = 0b00000000; cube[4][1] = 0b00000000; cube[5][1] = 0b00000000; cube[6][1] = 0b00000000; cube[7][1] = 0b00000000; 
  cube[0][2] = 0b00000000; cube[1][2] = 0b00000000; cube[2][2] = 0b00000000; cube[3][2] = 0b00000000; cube[4][2] = 0b00000000; cube[5][2] = 0b00000000; cube[6][2] = 0b00000000; cube[7][2] = 0b00000000; 
  cube[0][3] = 0b00000000; cube[1][3] = 0b00000000; cube[2][3] = 0b00000000; cube[3][3] = 0b00011000; cube[4][3] = 0b00011000; cube[5][3] = 0b00000000; cube[6][3] = 0b00000000; cube[7][3] = 0b00000000; 
  cube[0][4] = 0b00000000; cube[1][4] = 0b00000000; cube[2][4] = 0b00000000; cube[3][4] = 0b00011000; cube[4][4] = 0b00011000; cube[5][4] = 0b00000000; cube[6][4] = 0b00000000; cube[7][4] = 0b00000000; 
  cube[0][5] = 0b00000000; cube[1][5] = 0b00000000; cube[2][5] = 0b00000000; cube[3][5] = 0b00000000; cube[4][5] = 0b00000000; cube[5][5] = 0b00000000; cube[6][5] = 0b00000000; cube[7][5] = 0b00000000; 
  cube[0][6] = 0b00000000; cube[1][6] = 0b00000000; cube[2][6] = 0b00000000; cube[3][6] = 0b00000000; cube[4][6] = 0b00000000; cube[5][6] = 0b00000000; cube[6][6] = 0b00000000; cube[7][6] = 0b00000000; 
  cube[0][7] = 0b00000000; cube[1][7] = 0b00000000; cube[2][7] = 0b00000000; cube[3][7] = 0b00000000; cube[4][7] = 0b00000000; cube[5][7] = 0b00000000; cube[6][7] = 0b00000000; cube[7][7] = 0b00000000;
}

void draw(){
  // Repeat p many times before moving on to next frame 
  // change what p is less than; more for slower annimation, less for faster
  for(int p = 0; p < 10; p++){ 
    // Reset to first layer
    layerIndex = 0;
    for(int q = 0; q < 8; q++){
      // Reset to row 1
      rowIndex = 0;
      // Make shift registers accept new data
      digitalWrite(latchPin, LOW);
      // Shift out the layer data first
      shiftOut(dataPin, clockPin, MSBFIRST, 0b00000001 << layerIndex);    
      for(int t = 0; t < 8; t++){
        // Shift out the rows of data
        shiftOut(dataPin, clockPin, MSBFIRST, cube[layerIndex][rowIndex]);
        // Move onto the next row then repeat
        rowIndex++;                                                       
      }
      // Move onto the next layer and repeat
      layerIndex++;
      digitalWrite(latchPin, HIGH);
    }
  }
}

void setup() 
{
  // Setup the pin modes
  pinMode(dataPin,     OUTPUT);
  pinMode(clockPin,    OUTPUT);
  pinMode(latchPin,    OUTPUT);
  pinMode(masterClear, OUTPUT);

  // Clear the shift registers
  digitalWrite(masterClear, LOW);
  delay(10);
  digitalWrite(masterClear, HIGH);
}

void loop() 
{
  //Expanding Box Animation
  // Repeat 10 times
  for(int k = 0;k < 10;k++){
    box();
    draw();
    box2();
    draw();
    box3();
    draw();
    box4();
    draw();
    box3();
    draw();
    box2();
    draw();
  }
}

Best Answer

Basically, to use the program flow in this code, you need to break what you see going on there into distinct frames. Then replace the loop with calls to each frame function followed by draw(). Frames are snapshots of the cube evenly spaced in time. The more frames you have, the "smoother" the animation will look, but the more flash memory the program will take.

In the frame functions (e.g. box, box2, box3) of your example, the bits that are set to "1" in the frame buffer (i.e. the cube array variable) are the LEDs that are on in that frame, and those that are set to "0" are off in that frame. Each layer has 8 LEDs, so there is one bit per LED. You just have to map out and your LED pattern per frame.

Creating the hard-coded frame functions can be done by hand in this manner, by scripting the frame sequence. I think there are examples out there of people who have delegated this part to a PC that sends frames to the Arduino over the serial port to get more elaborate / smoother animations without having to store all the frame functions in the flash.