/* Arduino Projects for Dummies * by Brock Craft * * Chapter 15: Building an LED Cube * Drives animation on a 9x9x9 LED cube * * v0.1 30.04.2013 */ #include // Allows use of program memory space to store patterns // LED Pattern Table in program memory (PROGMEM) // The last column is the display time in units of 100ms. prog_uchar PROGMEM patternData[] = { // Blink all LEDs on and off B111, B111, B111, B111, B111, B111, B111, B111, B111, 10, B000, B000, B000, B000, B000, B000, B000, B000, B000, 10, B111, B111, B111, B111, B111, B111, B111, B111, B111, 10, B000, B000, B000, B000, B000, B000, B000, B000, B000, 10, // Test pattern showing each LED in order: // Left to Right columns, then // Front to Back rows, then // Top to Bottom plane B100, B000, B000, B000, B000, B000, B000, B000, B000, 1, B010, B000, B000, B000, B000, B000, B000, B000, B000, 1, B001, B000, B000, B000, B000, B000, B000, B000, B000, 1, B000, B100, B000, B000, B000, B000, B000, B000, B000, 1, B000, B010, B000, B000, B000, B000, B000, B000, B000, 1, B000, B001, B000, B000, B000, B000, B000, B000, B000, 1, B000, B000, B100, B000, B000, B000, B000, B000, B000, 1, B000, B000, B010, B000, B000, B000, B000, B000, B000, 1, B000, B000, B001, B000, B000, B000, B000, B000, B000, 1, B000, B000, B000, B100, B000, B000, B000, B000, B000, 1, B000, B000, B000, B010, B000, B000, B000, B000, B000, 1, B000, B000, B000, B001, B000, B000, B000, B000, B000, 1, B000, B000, B000, B000, B100, B000, B000, B000, B000, 1, B000, B000, B000, B000, B010, B000, B000, B000, B000, 1, B000, B000, B000, B000, B001, B000, B000, B000, B000, 1, B000, B000, B000, B000, B000, B100, B000, B000, B000, 1, B000, B000, B000, B000, B000, B010, B000, B000, B000, 1, B000, B000, B000, B000, B000, B001, B000, B000, B000, 1, B000, B000, B000, B000, B000, B000, B100, B000, B000, 1, B000, B000, B000, B000, B000, B000, B010, B000, B000, 1, B000, B000, B000, B000, B000, B000, B001, B000, B000, 1, B000, B000, B000, B000, B000, B000, B000, B100, B000, 1, B000, B000, B000, B000, B000, B000, B000, B010, B000, 1, B000, B000, B000, B000, B000, B000, B000, B001, B000, 1, B000, B000, B000, B000, B000, B000, B000, B000, B100, 1, B000, B000, B000, B000, B000, B000, B000, B000, B010, 1, B000, B000, B000, B000, B000, B000, B000, B000, B001, 10, // criscrossing planes B111, B111, B111, B000, B000, B000, B000, B000, B000, 1, B000, B000, B000, B111, B111, B111, B000, B000, B000, 1, B000, B000, B000, B000, B000, B000, B111, B111, B111, 1, B000, B000, B000, B111, B111, B111, B000, B000, B000, 1, B111, B111, B111, B000, B000, B000, B000, B000, B000, 1, B100, B100, B100, B100, B100, B100, B100, B100, B100, 1, B010, B010, B010, B010, B010, B010, B010, B010, B010, 1, B001, B001, B001, B001, B001, B001, B001, B001, B001, 1, B010, B010, B010, B010, B010, B010, B010, B010, B010, 1, B100, B100, B100, B100, B100, B100, B100, B100, B100, 1, //Pause B000, B000, B000, B000, B000, B000, B000, B000, B000, 10, // Orbiting column B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, B000, B100, B000, B000, B100, B000, B000, B100, B000, 1, B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, B000, B000, B010, B000, B000, B010, B000, B000, B010, 1, B000, B000, B001, B000, B000, B001, B000, B000, B001, 1, B000, B001, B000, B000, B001, B000, B000, B001, B000, 1, B001, B000, B000, B001, B000, B000, B001, B000, B000, 1, B010, B000, B000, B010, B000, B000, B010, B000, B000, 1, B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, B000, B100, B000, B000, B100, B000, B000, B100, B000, 1, B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, B000, B000, B010, B000, B000, B010, B000, B000, B010, 1, B000, B000, B001, B000, B000, B001, B000, B000, B001, 1, B000, B001, B000, B000, B001, B000, B000, B001, B000, 1, B001, B000, B000, B001, B000, B000, B001, B000, B000, 1, B010, B000, B000, B010, B000, B000, B010, B000, B000, 1, B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, B000, B100, B000, B000, B100, B000, B000, B100, B000, 1, B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, B000, B000, B010, B000, B000, B010, B000, B000, B010, 1, B000, B000, B001, B000, B000, B001, B000, B000, B001, 1, B000, B001, B000, B000, B001, B000, B000, B001, B000, 1, B001, B000, B000, B001, B000, B000, B001, B000, B000, 1, B010, B000, B000, B010, B000, B000, B010, B000, B000, 1, B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, B000, B100, B000, B000, B100, B000, B000, B100, B000, 1, B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, B000, B000, B010, B000, B000, B010, B000, B000, B010, 1, B000, B000, B001, B000, B000, B001, B000, B000, B001, 1, B000, B001, B000, B000, B001, B000, B000, B001, B000, 1, B001, B000, B000, B001, B000, B000, B001, B000, B000, 1, B010, B000, B000, B010, B000, B000, B010, B000, B000, 1, B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, // Two orbiting columns B100, B000, B001, B100, B000, B001, B100, B000, B001, 1, B000, B101, B000, B000, B101, B000, B000, B101, B000, 1, B001, B000, B100, B001, B000, B100, B001, B000, B100, 1, B010, B000, B010, B010, B000, B010, B010, B000, B010, 1, B100, B000, B001, B100, B000, B001, B100, B000, B001, 1, B000, B101, B000, B000, B101, B000, B000, B101, B000, 1, B001, B000, B100, B001, B000, B100, B001, B000, B100, 1, B010, B000, B010, B010, B000, B010, B010, B000, B010, 1, B100, B000, B001, B100, B000, B001, B100, B000, B001, 1, B000, B101, B000, B000, B101, B000, B000, B101, B000, 1, B001, B000, B100, B001, B000, B100, B001, B000, B100, 1, B010, B000, B010, B010, B000, B010, B010, B000, B010, 1, B100, B000, B001, B100, B000, B001, B100, B000, B001, 1, B000, B101, B000, B000, B101, B000, B000, B101, B000, 1, B001, B000, B100, B001, B000, B100, B001, B000, B100, 1, B010, B000, B010, B010, B000, B010, B010, B000, B010, 1, B100, B000, B001, B100, B000, B001, B100, B000, B001, 1, B000, B101, B000, B000, B101, B000, B000, B101, B000, 1, B001, B000, B100, B001, B000, B100, B001, B000, B100, 1, B010, B000, B010, B010, B000, B010, B010, B000, B010, 1, // Little cube to big cube B000, B000, B000, B000, B011, B011, B000, B011, B011, 10, B111, B111, B111, B111, B111, B111, B111, B111, B111, 10, B000, B000, B000, B000, B011, B011, B000, B011, B011, 5, B000, B000, B000, B000, B000, B000, B000, B000, B001, 2, B000, B000, B000, B000, B011, B011, B000, B011, B011, 2, B111, B111, B111, B111, B111, B111, B111, B111, B111, 2, B000, B000, B000, B000, B011, B011, B000, B011, B011, 2, B000, B000, B000, B000, B000, B000, B000, B000, B001, 2, B000, B000, B000, B000, B011, B011, B000, B011, B011, 2, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B000, B000, B000, B011, B011, B000, B011, B011, 1, B000, B000, B000, B000, B000, B000, B000, B000, B001, 1, B000, B000, B000, B000, B011, B011, B000, B011, B011, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B110, B110, B000, B110, B110, B000, B000, B000, B000, 1, B100, B000, B000, B000, B000, B000, B000, B000, B000, 1, B110, B110, B000, B110, B110, B000, B000, B000, B000, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B000, B000, B000, B011, B011, B000, B011, B011, 1, B000, B000, B000, B000, B000, B000, B000, B000, B001, 1, B000, B000, B000, B000, B011, B011, B000, B011, B011, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B110, B110, B000, B110, B110, B000, B000, B000, B000, 1, B100, B000, B000, B000, B000, B000, B000, B000, B000, 1, B110, B110, B000, B110, B110, B000, B000, B000, B000, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B011, B011, B000, B011, B011, B000, B000, B000, 1, B000, B000, B001, B000, B000, B000, B000, B000, B000, 1, B000, B011, B011, B000, B011, B011, B000, B000, B000, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B000, B000, B110, B110, B000, B110, B110, B000, 1, B000, B000, B000, B000, B000, B000, B100, B000, B000, 1, B000, B000, B000, B110, B110, B000, B110, B110, B000, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B011, B011, B000, B011, B011, B000, B000, B000, 1, B000, B000, B001, B000, B000, B000, B000, B000, B000, 1, B000, B011, B011, B000, B011, B011, B000, B000, B000, 1, B111, B111, B111, B111, B111, B111, B111, B111, B111, 1, B000, B000, B000, B110, B110, B000, B110, B110, B000, 1, B000, B000, B000, B000, B000, B000, B100, B000, B000, 1, B000, B000, B000, B110, B110, B000, B110, B110, B000, 1, // Diagonal wipe, starting in the center B111, B111, B111, B111, B111, B111, B111, B111, B111, 5, B111, B111, B111, B111, B111, B111, B111, B101, B111, 1, B111, B111, B111, B111, B101, B111, B111, B101, B111, 1, B111, B111, B111, B111, B101, B111, B111, B100, B111, 1, B111, B101, B111, B111, B100, B111, B111, B100, B110, 1, B111, B101, B111, B111, B100, B111, B111, B100, B110, 1, B111, B011, B111, B111, B100, B110, B111, B100, B100, 1, B111, B100, B110, B111, B100, B100, B111, B100, B000, 1, B111, B100, B100, B111, B100, B000, B111, B000, B000, 1, B111, B100, B000, B111, B000, B000, B011, B000, B000, 1, B111, B000, B000, B011, B000, B000, B001, B001, B000, 1, // A 2-LED wide diaginal stripe that orbits the cube B011, B000, B000, B001, B001, B000, B000, B001, B001, 1, B001, B001, B000, B000, B001, B001, B000, B000, B011, 1, B000, B001, B001, B000, B000, B011, B000, B000, B110, 1, B000, B000, B011, B000, B000, B110, B000, B100, B100, 1, B000, B000, B110, B000, B100, B100, B100, B100, B000, 1, B000, B100, B100, B100, B100, B000, B110, B000, B000, 1, B100, B100, B000, B110, B000, B000, B011, B000, B000, 1, B110, B000, B000, B011, B000, B000, B001, B001, B000, 1, B011, B000, B000, B001, B001, B000, B000, B001, B001, 1, B001, B001, B000, B000, B001, B001, B000, B000, B011, 1, B000, B001, B001, B000, B000, B011, B000, B000, B110, 1, B000, B000, B011, B000, B000, B110, B000, B100, B100, 1, B000, B000, B110, B000, B100, B100, B100, B100, B000, 1, B000, B100, B100, B100, B100, B000, B110, B000, B000, 1, B100, B100, B000, B110, B000, B000, B011, B000, B000, 1, B110, B000, B000, B011, B000, B000, B001, B001, B000, 1, //Pause B000, B000, B000, B000, B000, B000, B000, B000, B000, 10, }; const int cubeSize=3; // The dimensions of the cube, in LEDs const int planeSize=9; // The number of LEDs on each plane of the cube const int planeDisplayTime=1000; // The time each plane is displayed in microseconds const int updateSpeed=100; // Multiplier for displayTime to get milliseconds byte patternBuffer[planeSize]; // Stores the current pattern from patternData int patternIndex; // Keeps track of the line of the pattern being displayed int patternBufferIndex; // Counts where we are while painting the display byte displayTime; // Multiplied by 100ms to set the frame duration unsigned long endTime; // Tracks when we are finished with the frame int ledrow; // Counts LED rows in the refresh loop int ledcol; // Counts LEDs columns in the refresh loop int ledpin; // Counts LEDs in the refresh loop // Defining pins in array makes it easier to access them in the program // and change how they are wired up, if necessary. int LEDPin[] = {2,3,4,5,6,7,8,9,10}; int PlanePin[] = {14,15,16}; void setup() { // set up LED pins as output (active HIGH) for (int i=0; i0 do { // memcpy is copies the data from the Program Memory (PROMGMEM) into a temporary array buffer // called pattern buffer. This will be used to determine what to light up memcpy_P( patternBuffer, patternData+patternIndex, planeSize ); // The size of the pattern index is incremented by 9, which keeps track of // where we are getting our data from in the pattern Buffer. // It will be reset back to 0 after all three planes are displayed. patternIndex += planeSize; // Read the displayTime from PROGMEM and increment the pattern index to get the right values. // The displayTime is every 10th data element. displayTime = pgm_read_byte_near( patternData + patternIndex++ ); // Calculate the endTime from the current time (ms) and the displayTime endTime = millis() + displayTime * updateSpeed; // loop while displayTime>0 and current time < endTime while ( millis() < endTime ) { patternBufferIndex = 0; // reset index counter to beginning of buffer // Loop over the planes of the cube for (int plane=0; plane 0); // read patterns until time=0 which signals end }