led-cube 15x

mic-hasch

Member
I'm looking for good animations for my 15³ LED cube. Since I chose an odd edge length to have a true center, I can't really use most of the examples available. except for the hassle of defining each scene pixel by pixel and running lines from one point to another makes it look bad.. At least I managed to translate the LED number to the xyz position. also parallel output via fastled.h on 15 channels with teensy4.1. I have attached my last attempt, in which the surface should move from one side to the other. Unfortunately the translation doesn't work here, so every second level is mirrored. I intentionally didn't delete the attempts from the code to show my approaches. Hopefully this isn't too confusing.

the 2nd code is cleaned up



Code:
#include <FastLED.h>


#define LED_TYPE    WS2811
#define COLOR_ORDER RGB


#define NUM_LEDS_PER_STRIPp 225
#define NUM_STRIPS 15
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIPp];
#define NUM_LEDS_PER_STRIP    3375
#define BRIGHTNESS          255
#define FRAMES_PER_SECOND  100
#define SIZE 15
uint8_t brightness = 250;
uint8_t hue = 0;
uint8_t fade = 0;

const int width = 15;
const int height = 15;
const int depth = 15;

uint32_t counter = 0;
uint32_t plane = 0;
uint16_t prev[SIZE * SIZE] = {0};




 

void setup() {
    FastLED.setMaxPowerInMilliWatts(350000); //max 100W for this power supply
    delay(1000);
//FastLED.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIPp);
FastLED.addLeds<NUM_STRIPS, WS2811, 1>(leds,NUM_LEDS_PER_STRIPp);

  FastLED.setBrightness(BRIGHTNESS);
    

}

 
 
void loop() {
 
      
    
 EVERY_N_MILLISECONDS(8)    {
    memset(leds, 0, sizeof(leds));
   for (uint8_t k = 0; k < SIZE; k++) {
      for (uint8_t j = 0; j < SIZE; j++) {
        int o = counter / (j + 1);
        if (o < 0) {
          o = 0;
        }
        if (o >= SIZE) {
          o = SIZE - 1;
        }
      

uint8_t x, y, z;
 
 switch (plane){
          case 0: x = k; y = j; z = o; break;
          case 1: x = k; y = j; z = SIZE - 1 - o; break;
          case 2: x = k; z = j; y = o; break;
          case 3: x = k; z = j; y = SIZE - 1 - o; break;
          case 4: z = k; y = j; x = o; break;
          case 5: z = k; y = j; x = SIZE - 1 - o; break;
           }
           leds[z * SIZE * SIZE + y * SIZE + x] = CHSV(hue, 255, 255);
           }}
counter++;
   if (counter == SIZE * SIZE) {
    counter = 0;
      plane = (plane + 1) % 6;
      hue += 6;
    }
          
 
 FastLED.show();
        
  
}
}


Code:
//Rays going through the led cube space (should be generalizable to cubes made of stacked symmetrical layers each arranged in a serpentine layout)
//Right now limited to simple lines with slope of -1,0 or 1 but would like to extend to any line or even curves or sine waves? Not sure if it's worth trying on a display of 9x9x9 resolution though
//#define USE_OCTOWS2811
//#include <OctoWS2811.h>
#include <FastLED.h>


#define LED_TYPE    WS2811
#define COLOR_ORDER RGB


#define NUM_LEDS_PER_STRIPp 225
#define NUM_STRIPS 15
CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIPp];
#define NUM_LEDS_PER_STRIP    3375
#define BRIGHTNESS          255
#define FRAMES_PER_SECOND  100
#define SIZE 15
uint8_t brightness = 250;
uint8_t hue = 0;
uint8_t fade = 0;
uint8_t delaytime = 1;
uint16_t delaytime1;
uint16_t delaytime2;
uint16_t delaytime3;
const int width = 15;
const int height = 15;
const int depth = 15;
uint32_t counter = 0;
uint32_t plane = 0;
uint16_t prev[SIZE * SIZE] = {0};

byte die6D=0;
byte die6z=0;
byte xp=0;
byte yp=0;
byte zp=0;
byte xc=-1;
byte yc=1;
byte zc=1;

//FUNCTIONS
//xy to led number translation from FastLED extended to z dimension and protected from out of range  erwitert um wechsel z
uint16_t XYZ( uint8_t x, uint8_t y, uint8_t z) {


  uint16_t i;


  if (x < width && y < height && z < depth) {
    if ( z & 1) {  //ebene gerade
      if ( y & 1) {  //line gerade
        uint8_t reverseY = (height - 1) - y;
        i = (reverseY * width) + x;  //lines run rückwards

      } else {
        uint8_t reverseY = (height - 1) - y;
        uint8_t reverseX = (width - 1) - x;
        i = (reverseY * width) + reverseX; // Odd lines run rückwards und  Odd rows run rückwards
      }
    } else {  //ebene ungerade
      if ( y & 1) {
        // Odd rows run backwards
        uint8_t reverseX = (width - 1) - x;
        i = (y * width) + reverseX;
      } else {
        // Even rows run forwards
        i = (y * width) + x;// Even rows run forwards
      }

    
    }
  
  i = i + (z * width * height);
 
  return i;
    } else {
      return 0;
    }
}
uint16_t KJO( uint8_t k, uint8_t j, uint8_t o) {


  uint16_t i;


  if (k < width && j < height && o < depth) {
    if ( o & 1) {  //ebene gerade
      if ( k & 1) {  //line gerade
        uint8_t reverseJ = (height - 1) - j;
        i = (reverseJ * width) + k;  //lines run rückwards

      } else {
        uint8_t reverseJ = (height - 1) - j;
        uint8_t reverseK = (width - 1) - k;
        i = (reverseJ * width) + reverseK; // Odd lines run rückwards und  Odd rows run rückwards
      }
    } else {  //ebene ungerade
      if ( j & 1) {
        // Odd rows run backwards
        uint8_t reverseK = (width - 1) - k;
        i = (j * width) + reverseK;
      } else {
        // Even rows run forwards
        i = (j * width) + k;// Even rows run forwards
      }

    
    }
  
  i = i + (o * width * height);
 
  return i;
    } else {
      return 0;
    }
}

  //position and movement variables
  int x;
  int y;
  int z;

  int k;
  int j;
  int o;
 
  int xchange;
  int ychange;
  int zchange;

 

void setup() {
    FastLED.setMaxPowerInMilliWatts(350000); //max 100W for this power supply
    delay(1000);
//FastLED.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIPp);
FastLED.addLeds<NUM_STRIPS, WS2811, 1>(leds,NUM_LEDS_PER_STRIPp);

  FastLED.setBrightness(BRIGHTNESS);
    
randomSeed(255);
}

 
 
void loop() {
  //choose random face to "enter" from and starting position on that face,
  //and how the line is going to move
 // int ledToLight = XYZ(x,y,z);
      //int ledToLight = XYZ(x+1,y+1,z+1);
      
    
 EVERY_N_MILLISECONDS(8)   // minimum 8
 {
    memset(leds, 0, sizeof(leds)); { {
/*    for (uint8_t k = 0; k < SIZE; k++) {
      for (uint8_t j = 0; j < SIZE; j++) {
        int o = counter / (j + 1);
        if (o < 0) {
          o = 0;
        }
        if (o >= SIZE) {
          o = SIZE - 1;
        }
       */
  /*     if(k>15)
  {
    k=0;
  }
   if(xp<0)
  {
    xc=1;
  }*/
  k++;
  if(k>14)
  {
    k=0;
    j++;
     }
  if(j>14)
  {
    j=0;
    o++;
  }
  for (uint8_t k = 0; k < SIZE; k++) {
      for (uint8_t j = 0; j < SIZE; j++) {
   int o = counter / (j + 1);
        if (o < 0) {
          o = 0;
        }
        if (o >= SIZE) {
          o = SIZE - 1;
        }
 // counter++;
  /*if(die6D>29)
  {
    die6D=0;
  } */
//        hue = analogRead(5); //use pot to control color
// brightness = analogRead(10);
// delaytime1 = analogRead(8);
 //delaytime2 = analogRead(7);
// delaytime3 = analogRead(6);
//       fade = analogRead(9); 
 //uint8_t x, y, z;
 
 switch (plane){
          case 0: x = k; y = j; z = o; break;
          case 1: x = k; y = j; z = SIZE - 1 - o; break;
          case 2: x = k; z = j; y = o; break;
          case 3: x = k; z = j; y = SIZE - 1 - o; break;
          case 4: z = k; y = j; x = o; break;
          case 5: z = k; y = j; x = SIZE - 1 - o; break;
           }
           leds[z * SIZE * SIZE + y * SIZE + x] = CHSV(hue, 255, 255);
           }}
counter++;
   if (counter == SIZE * SIZE) {
    counter = 0;
      plane = (plane + 1) % 6;
      hue += 6;
    }
          
  //e.g. in this first case we start on the x=0 face and a random y and z position. we limit the movement in the x direction to positive but allow movement in y and z direction to be positive, negative or stationary
  /*  case 0:

/*
 *//*if(die6z>3)
  {
    die6z=0;
  }

  switch(die6z){
  */
  /*
    x = 0;
    y = 0;
    z =die6z;
    xchange = 1;
    ychange = 1;
    zchange = 1;
    die6z++;
    break;
   // }
    
    break;

    case 1:
    x = 7;
    y = 14;
    z = 0;
    xchange = 0;
    ychange = -1;
    zchange = 1;
 break;

  
    case 2:
    x = 0;
    y = 14;
    z = 0;
    xchange = 1;
    ychange = -1;
    zchange = 1;
    break;
    
    case 3:
    x = 14;
    y = 14;
    z = 0;
    xchange = -1;
    ychange = -1;
    zchange = 1;
    break;
 
    case 4:
    x = 7;
    y = 0;
    z = 0;
    xchange = 0;
    ychange = 1;
    zchange = 1;
    break;
    
    case 5:
    x = 0;
    y = 7;
    z = 0;
    xchange = 1;
    ychange = 0;
    zchange =1;
    break;

     case 6:
    x = 0;
    y = 0;
    z = 7;
    xchange =1 ;
    ychange = 1;
    zchange =0;
    break;

    case 7:
    x = 0;
    y = 7;
    z = 7;
    xchange =1 ;
    ychange = 0;
    zchange =0;
    break;

   case 8:
    x = 7;
    y = 14;
    z = 7;
    xchange =0;
    ychange = -1;
    zchange =0;
    break;

    case 9:
    x = 7;
    y = 7;
    z = 14;
    xchange =0 ;
    ychange = 0;
    zchange = -1;
    break;
    
    case 10:
    x = 7;
    y = 7;
    z = 0;
    xchange =0;
    ychange = 0;
    zchange =1;
    break;
 
  case 11:
    x = 0;
    y = 14;
    z = 7;
    xchange =1;
    ychange = -1;
    zchange =0;
    break;

     case 12:
    x = 14;
    y = 0;
    z = 0;
    xchange =-1;
    ychange = 1;
    zchange = 1;
    break;

    case 13:
    x = 14;
    y = 7;
    z = 0;
    xchange = -1;
    ychange = 0;
    zchange = 1;
    break;
    case 14:
    x = 0;
    y = 0;
    z = 0;
    xchange = 1;
    ychange = 0;
    zchange = 0;
    break;
    case 15:
     x = 0;
    y = 0;
    z = 14;
    xchange = 1;
    ychange = 0;
    zchange = 0;
    break;
case 16:
     x = 0;
    y = 14;
    z = 14;
    xchange = 1;
    ychange = 0;
    zchange = 0;
    break;
case 17:
     x = 0;
    y = 14;
    z = 0;
    xchange = 1;
    ychange = 0;
    zchange = 0;
    break;
    case 18:
     x = 0;
    y = 0;
    z = 14;
    xchange = 0;
    ychange = 1;
    zchange = 0;
    break;
    case 19:
     x = 0;
    y = 0;
    z = 0;
    xchange = 0;
    ychange = 1;
    zchange = 0;
    break;
    case 20:
     x = 14;
    y = 0;
    z = 14;
    xchange = 0;
    ychange = 1;
    zchange = 0;
    break;
    case 21:
     x = 14;
    y = 0;
    z = 0;
    xchange = 0;
    ychange = 1;
    zchange = 0;
    break;
    case 22:
     x = 0;
    y = 0;
    z = 0;
    xchange = 0;
    ychange = 0;
    zchange = 1;
    break;
    case 23:
     x = 0;
    y = 14;
    z = 0;
    xchange = 0;
    ychange = 0;
    zchange = 1;
    break;
    case 24:
     x = 14;
    y = 0;
    z = 0;
    xchange = 0;
    ychange = 0;
    zchange = 1;
    break;
    case 25:
     x = 14;
    y = 14;
    z = 0;
    xchange = 0;
    ychange = 0;
    zchange = 1;
    break;
    case 26:
     x = 7;
    y = 7;
    z = 14;
    xchange = 1;
    ychange = 2;
    zchange = 0;
    break;
    case 27:
     x = 7;
    y = 7;
    z = 14;
    xchange = 1;
    ychange = 1;
    zchange = 0;
    break;
    case 28:
     x = 7;
    y = 7;
    z = 14;
    xchange = 2;
    ychange = 1;
    zchange = 0;
break;
case 29:
     x = 7;
    y = 7;
    z = 14;
    xchange = 1;
    ychange = 0;
    zchange = 0;
  break; 




  }*/

    //once starting position and movement direction decided, add the change value
    //to each coord, convert to led number and display, until one hits a face
    //(x,y or z = 0 or width/height/depth-1)
  /*  if(xp>15)
  {
    xp=0;
  }*/
 /*  if(xp<0)
  {
    xc=1;
  }
  if(xp>14)
  {
    xc=-1;
     }
  if(yp>14)
  {
    yp=0;
  }
   if(zp>14)
  {
    zp=0;
  }
    
    x = xp;
    y = yp;
    z = zp;
    xchange = xc;
    ychange = 0;
    zchange = 1;
        
    while(x>=0 && x<width && y>=0 && y<height && z>=0 && z<depth){
      
      int ledToLight = XYZ(x,y,z);
      //int ledToLight = XYZ(x+1,y+1,z+1);
      leds[ledToLight] = (CHSV(hue,255,brightness));
      FastLED.show();
      
      fadeToBlackBy(leds, NUM_LEDS_PER_STRIP, fade);
      
      x = x + xchange;
      y = y + ychange;
      z = z + zchange;

      delay(1);
    
  }
    x = xp;
    y = yp;
    z = zp;
    xchange = 0;
    ychange = 0;
    zchange = 1;

     while(x>=0 && x<width && y>=0 && y<height && z>=0 && z<depth){
      
      int ledToLight = XYZ(x,y,z);
      //int ledToLight = XYZ(x+1,y+1,z+1);
      leds[ledToLight] = (CHSV(hue,255,brightness));
      FastLED.show();
      
      fadeToBlackBy(leds, NUM_LEDS_PER_STRIP, fade);
      
      x = x + xchange;
      y = y + ychange;
      z = z + zchange;

      delay(0);

       }
 x = xp;
    y = yp;
    z = zp;
    xchange = 0;
    ychange = 0;
    zchange = 1;

     while(x>=0 && x<width && y>=0 && y<height && z>=0 && z<depth){
      
      int ledToLight = XYZ(x,y,z);
      //int ledToLight = XYZ(x+1,y+1,z+1);
      leds[ledToLight] = (CHSV(hue,255,brightness));
      FastLED.show();
      
      fadeToBlackBy(leds, NUM_LEDS_PER_STRIP, fade);
      
      x = x + xchange;
      y = y + ychange;
      z = z + zchange;

      delay(0);

       }   
 
     x = xp;
    y = 0;
    z = zp;
    xchange = 1;
    ychange = 1;
    zchange = 0;

 */   /* while(x>=0 && x<width && y>=0 && y<height && z>=0 && z<depth){
      
      int ledToLight = XYZ(x,y,z);
      //int ledToLight = XYZ(x+1,y+1,z+1);
      leds[ledToLight] = (CHSV(hue,255,brightness));
      
      
      fadeToBlackBy(leds, NUM_LEDS_PER_STRIP, fade);  }
      counter++;
    if (counter == SIZE * SIZE) {
      counter = 0;
      plane = (plane + 1) % 6;
      hue += 16;
    }
  
    
      x = x + xchange;
      y = y + ychange;
      z = z + zchange;

      delay(0);*/
 FastLED.show();
        
   /*
    //continue fading out and random time until next line appears
    
   /* int timelim = random(1);
    
    for(int i=0; i<timelim; i++){
      fadeToBlackBy(leds, NUM_LEDS_PER_STRIP, fade);
      delay(1);
      FastLED.show();
    }
    */
//xp++;
//yp++;
//zp++;
//int xc;
//die6D++;
// hue = hue+10; //move through rainbow every cycle 
}
}
}
}
 
Years ago I built an 8x8x8 cube using an arduino uno (ATmega328 processor). I display several animations, sixteen frames each pre-calculated and stored in flash. I have the "Sombrero Function", a wave, a spiral, and a rotating caltrop/jack. In addition I have dynamic animations of rain, worms, and fireworks. Once a minute I scroll the time and date across four faces. I have perl code to compute the data stored in flash, but it's for an 8x8x8 cube so it will need modification for your 15x15x15 cube.
 
Years ago I built an 8x8x8 cube using an arduino uno (ATmega328 processor). I display several animations, sixteen frames each pre-calculated and stored in flash. I have the "Sombrero Function", a wave, a spiral, and a rotating caltrop/jack. In addition I have dynamic animations of rain, worms, and fireworks. Once a minute I scroll the time and date across four faces. I have perl code to compute the data stored in flash, but it's for an 8x8x8 cube so it will need modification for your 15x15x15 cube.
I would like to take a look at that.would you send me the code?
 
I've attached a zip file of the perl code and the perl code output. For the 8x8x8 cube I'm only storing one bit per LED in flash. A random color is selected before the animation starts and every point has the same color. The rain/fireworks/worms code (not included) uses varying colors.
 

Attachments

  • anim.zip
    6.7 KB · Views: 503
A simple animation is to pick one of the eight corners and draw a wire-frame cube at the corner, starting with a line of length one, then two, then three, and so on until the entire 15x15x15 cube is outlined. Start reducing the line length back down to a single point, then choose another corner.
 
Back
Top