/** * LED_Cube * * Code for an Arduino Mega to control an LED cube. Ports 0 to 48 should * switch the columns, with (0,0 to 6) going to ports 0 to 6, * (1,0 to 6) going to ports 7 to 13, etc. * * Ports A0 through A6 control the layers with A0 controlling z = 0 and A6 * controlling z = 6. * * Ports A8 to A15 serve as inputs for the pushbutton switches. * * Original at: http://www.instructables.com/id/Self-Contained-7x7x7-LED-Cube/ * Program written by Lopuz3 * Spring 2013 * * _____________________________________________________________________________ * Modified by joergeli / Autumn 2014 * http://arduino.joergeli.de/ledcube/ledcube.php * * * Reduced amount of buttons to only 1 Button at Port A8, which toggles through all effects. * Added a switch at Port 53 to choose manual- or automatic-mode: * In manual-mode the effects can be choosen by multiple pressing the button on Port A8. * In automatic-mode all effects are choosen time-driven one after the other. * Duration of automatic-effects then depends on value of variable "interval", * ( look at section "switch (effektcounter) ... case ... interval=xxxx") * * Renamed most of libraries for better recognizing to which sketch they belong. * Added some libraries for more effects (not optimal programmed, but they work ;-) * **/ long previousMillis = 0; long interval = 1000; // used for time-based switching of effects (milliseconds) int effektcounter=0; int autoswitch = 53; // Switch on port 53 for manual-/auto-mode int val_autoswitch = 0; #include #include #include #include #include #include #include #include #include #include #include #include #include // Added some libraries: #include #include #include #include #include #include #include #include #include #include #define CUBE_SIZE 7 #define NUM_BUTTONS 1 // reduced to 1 button #define REFRESH_RATE 60 Cube_PushButton buttons[NUM_BUTTONS]; Cube_View cube = Cube_View(); Routine *currentRoutine = new Routine(); boolean lastCompleteFrame[CUBE_SIZE][CUBE_SIZE][CUBE_SIZE]; void setup() { setUpButtons(); setUpInterrupts(); pinMode(autoswitch, INPUT); delete currentRoutine; currentRoutine = new Cube_AllOn(); } void setUpInterrupts() { cli();//stop interrupts while we set them up //set up an interrupt with timer1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; //make the interrupt ocurr at the correct frequency. The frequency is REFRESH_RATE*CUBE_SIZE OCR1A = (16000000/REFRESH_RATE/1024/CUBE_SIZE -1); TCCR1B |= (1 << WGM12); // Set to CS10 and CS12 so we have the 1024 TCCR1B |= (1 << CS12) | (1 << CS10); TIMSK1 |= (1 << OCIE1A); sei();//reallow interrupts } void setUpButtons() { for(byte i = 0 ; i < NUM_BUTTONS ; i++) { buttons[i] = Cube_PushButton(i+A8); } } //Called by timer interrupt ISR(TIMER1_COMPA_vect) { cube.displayLayer(lastCompleteFrame); } void loop() { currentRoutine->update(getTimeSinceLastFrameInMicros()); memcpy(&lastCompleteFrame, ¤tRoutine->cubeModel, sizeof(boolean)*CUBE_SIZE*CUBE_SIZE*CUBE_SIZE); val_autoswitch = digitalRead(autoswitch); if(val_autoswitch == 0){ getButtonInput(); } // = manual-mode else if (val_autoswitch !=0){ // = automatic-mode unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; effektcounter=effektcounter+1; switch (effektcounter) { case 1: delete currentRoutine; currentRoutine = new Cube_Sin(); interval=15000; break; case 2: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 3: delete currentRoutine; currentRoutine = new Cube_WanderingWalls(); interval=20000; break; case 4: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 5: delete currentRoutine; currentRoutine = new Cube_CornerToCorner(); interval=20300; break; case 6: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 7: delete currentRoutine; currentRoutine = new Cube_Frame(); interval=14600; break; case 8: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 9: delete currentRoutine; currentRoutine = new Cube_Fade(); interval=28000; break; case 10: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 11: delete currentRoutine; currentRoutine = new Cube_FlippingWall(); interval=25000; break; case 12: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 13: delete currentRoutine; currentRoutine = new Cube_Ripple(); interval=15000; break; case 14: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 15: delete currentRoutine; currentRoutine = new Cube_BouncingBall(); interval=16000; break; case 16: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 17: delete currentRoutine; currentRoutine = new Cube_OpenBox(); interval=12000; break; case 18: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 19: delete currentRoutine; currentRoutine = new Cube_Wave(); interval=15000; break; case 20: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 21: delete currentRoutine; currentRoutine = new Cube_Mover(); interval=15000; break; case 22: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 23: delete currentRoutine; currentRoutine = new Cube_Firework(); interval=15000; break; case 24: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 25: delete currentRoutine; currentRoutine = new Cube_WheelH(); interval=10000; break; case 26: delete currentRoutine; currentRoutine = new Cube_Wheel(); interval=12000; break; case 27: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 28: delete currentRoutine; currentRoutine = new Cube_VertSin(); interval=20000; break; case 29: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 30: delete currentRoutine; currentRoutine = new Cube_PouringRain(); interval=68700; break; case 31: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 32: delete currentRoutine; currentRoutine = new Cube_Full(); interval=12000; break; case 33: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; case 34: delete currentRoutine; currentRoutine = new Cube_Hammer(); interval=20000; break; case 35: delete currentRoutine; currentRoutine = new Cube_AllOn(); interval=850; break; } // end of switch if(effektcounter>35){effektcounter=0;}; } // end of Millis } // end of val_autoswitch } // end of loop void getButtonInput(){ if(anyButtonWasPressed()) { effektcounter=effektcounter+1; if(effektcounter > 18){effektcounter = 1;}; delete currentRoutine; currentRoutine = new Cube_AllOn(); } if (buttons[0].wasReleased()) { //Serial.println(effekt); // for debugging switch (effektcounter) { case 1: delete currentRoutine; currentRoutine = new Cube_Sin(); break; case 2: delete currentRoutine; currentRoutine = new Cube_WanderingWalls(); break; case 3: delete currentRoutine; currentRoutine = new Cube_CornerToCorner(); break; case 4: delete currentRoutine; currentRoutine = new Cube_Frame(); break; case 5: delete currentRoutine; currentRoutine = new Cube_Fade(); break; case 6: delete currentRoutine; currentRoutine = new Cube_FlippingWall(); break; case 7: delete currentRoutine; currentRoutine = new Cube_Ripple(); break; case 8: delete currentRoutine; currentRoutine = new Cube_BouncingBall(); break; case 9: delete currentRoutine; currentRoutine = new Cube_Hammer(); break; case 10: delete currentRoutine; currentRoutine = new Cube_OpenBox(); break; case 11: delete currentRoutine; currentRoutine = new Cube_Wave(); break; case 12: delete currentRoutine; currentRoutine = new Cube_Mover(); break; case 13: delete currentRoutine; currentRoutine = new Cube_Firework(); break; case 14: delete currentRoutine; currentRoutine = new Cube_WheelH(); break; case 15: delete currentRoutine; currentRoutine = new Cube_Wheel(); break; case 16: delete currentRoutine; currentRoutine = new Cube_PouringRain(); break; case 17: delete currentRoutine; currentRoutine = new Cube_VertSin(); break; case 18: delete currentRoutine; currentRoutine = new Cube_Full(); break; } // end of switch } } boolean anyButtonWasPressed() { for(byte i = 0 ; i < NUM_BUTTONS ; i++) { if(buttons[i].wasPressed()) { return true; } } return false; } /*Get the time since the last call of this function in microseconds*/ unsigned long getTimeSinceLastFrameInMicros() { static unsigned long lastTime = 0; unsigned long dt = micros()-lastTime; lastTime = micros(); return dt; }