]> git.piffa.net Git - arduino/blob - books/pdummies/APFD_Chapter15_LED_Cube/APFD_Chapter15_LED_Cube.ino
first commit
[arduino] / books / pdummies / APFD_Chapter15_LED_Cube / APFD_Chapter15_LED_Cube.ino
1 /* Arduino Projects for Dummies
2  * by Brock Craft 
3  *
4  * Chapter 15: Building an LED Cube
5  * Drives animation on a 9x9x9 LED cube
6  *
7  * v0.1 30.04.2013
8 */
9
10 #include <avr/pgmspace.h> // Allows use of program memory space to store patterns
11
12 // LED Pattern Table in program memory (PROGMEM)
13 // The last column is the display time in units of 100ms.
14
15 prog_uchar PROGMEM patternData[] = {
16   // Blink all LEDs on and off
17   B111, B111, B111, B111, B111, B111, B111, B111, B111, 10,
18   B000, B000, B000, B000, B000, B000, B000, B000, B000, 10,
19   B111, B111, B111, B111, B111, B111, B111, B111, B111, 10,
20   B000, B000, B000, B000, B000, B000, B000, B000, B000, 10,
21   
22   // Test pattern showing each LED in order:
23   // Left to Right columns, then
24   // Front to Back rows, then
25   // Top to Bottom plane
26   B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
27   B010, B000, B000, B000, B000, B000, B000, B000, B000, 1,
28   B001, B000, B000, B000, B000, B000, B000, B000, B000, 1,
29   B000, B100, B000, B000, B000, B000, B000, B000, B000, 1,
30   B000, B010, B000, B000, B000, B000, B000, B000, B000, 1,
31   B000, B001, B000, B000, B000, B000, B000, B000, B000, 1,
32   B000, B000, B100, B000, B000, B000, B000, B000, B000, 1,
33   B000, B000, B010, B000, B000, B000, B000, B000, B000, 1,
34   B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
35   B000, B000, B000, B100, B000, B000, B000, B000, B000, 1,
36   B000, B000, B000, B010, B000, B000, B000, B000, B000, 1,
37   B000, B000, B000, B001, B000, B000, B000, B000, B000, 1,
38   B000, B000, B000, B000, B100, B000, B000, B000, B000, 1,
39   B000, B000, B000, B000, B010, B000, B000, B000, B000, 1,
40   B000, B000, B000, B000, B001, B000, B000, B000, B000, 1,
41   B000, B000, B000, B000, B000, B100, B000, B000, B000, 1,
42   B000, B000, B000, B000, B000, B010, B000, B000, B000, 1,
43   B000, B000, B000, B000, B000, B001, B000, B000, B000, 1,
44   B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
45   B000, B000, B000, B000, B000, B000, B010, B000, B000, 1,
46   B000, B000, B000, B000, B000, B000, B001, B000, B000, 1,
47   B000, B000, B000, B000, B000, B000, B000, B100, B000, 1,
48   B000, B000, B000, B000, B000, B000, B000, B010, B000, 1,
49   B000, B000, B000, B000, B000, B000, B000, B001, B000, 1,
50   B000, B000, B000, B000, B000, B000, B000, B000, B100, 1,
51   B000, B000, B000, B000, B000, B000, B000, B000, B010, 1,
52   B000, B000, B000, B000, B000, B000, B000, B000, B001, 10,
53   
54   // criscrossing planes
55   B111, B111, B111, B000, B000, B000, B000, B000, B000, 1,
56   B000, B000, B000, B111, B111, B111, B000, B000, B000, 1,    
57   B000, B000, B000, B000, B000, B000, B111, B111, B111, 1,
58   B000, B000, B000, B111, B111, B111, B000, B000, B000, 1,    
59   B111, B111, B111, B000, B000, B000, B000, B000, B000, 1,
60   B100, B100, B100, B100, B100, B100, B100, B100, B100, 1, 
61   B010, B010, B010, B010, B010, B010, B010, B010, B010, 1,
62   B001, B001, B001, B001, B001, B001, B001, B001, B001, 1,
63   B010, B010, B010, B010, B010, B010, B010, B010, B010, 1,
64   B100, B100, B100, B100, B100, B100, B100, B100, B100, 1,
65   
66   //Pause
67   B000, B000, B000, B000, B000, B000, B000, B000, B000, 10, 
68   
69   // Orbiting column
70   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1,  
71   B000, B100, B000, B000, B100, B000, B000, B100, B000, 1,    
72   B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, 
73   B000, B000, B010, B000, B000, B010, B000, B000, B010, 1,
74   B000, B000, B001, B000, B000, B001, B000, B000, B001, 1,
75   B000, B001, B000, B000, B001, B000, B000, B001, B000, 1,
76   B001, B000, B000, B001, B000, B000, B001, B000, B000, 1,
77   B010, B000, B000, B010, B000, B000, B010, B000, B000, 1,
78   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, 
79   B000, B100, B000, B000, B100, B000, B000, B100, B000, 1,    
80   B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, 
81   B000, B000, B010, B000, B000, B010, B000, B000, B010, 1,
82   B000, B000, B001, B000, B000, B001, B000, B000, B001, 1,
83   B000, B001, B000, B000, B001, B000, B000, B001, B000, 1,
84   B001, B000, B000, B001, B000, B000, B001, B000, B000, 1,
85   B010, B000, B000, B010, B000, B000, B010, B000, B000, 1,
86   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1,
87   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1,  
88   B000, B100, B000, B000, B100, B000, B000, B100, B000, 1,    
89   B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, 
90   B000, B000, B010, B000, B000, B010, B000, B000, B010, 1,
91   B000, B000, B001, B000, B000, B001, B000, B000, B001, 1,
92   B000, B001, B000, B000, B001, B000, B000, B001, B000, 1,
93   B001, B000, B000, B001, B000, B000, B001, B000, B000, 1,
94   B010, B000, B000, B010, B000, B000, B010, B000, B000, 1,
95   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1, 
96   B000, B100, B000, B000, B100, B000, B000, B100, B000, 1,    
97   B000, B000, B100, B000, B000, B100, B000, B000, B100, 1, 
98   B000, B000, B010, B000, B000, B010, B000, B000, B010, 1,
99   B000, B000, B001, B000, B000, B001, B000, B000, B001, 1,
100   B000, B001, B000, B000, B001, B000, B000, B001, B000, 1,
101   B001, B000, B000, B001, B000, B000, B001, B000, B000, 1,
102   B010, B000, B000, B010, B000, B000, B010, B000, B000, 1,
103   B100, B000, B000, B100, B000, B000, B100, B000, B000, 1,
104
105   // Two orbiting columns 
106   B100, B000, B001, B100, B000, B001, B100, B000, B001, 1,
107   B000, B101, B000, B000, B101, B000, B000, B101, B000, 1,
108   B001, B000, B100, B001, B000, B100, B001, B000, B100, 1,
109   B010, B000, B010, B010, B000, B010, B010, B000, B010, 1,
110   B100, B000, B001, B100, B000, B001, B100, B000, B001, 1,
111   B000, B101, B000, B000, B101, B000, B000, B101, B000, 1,
112   B001, B000, B100, B001, B000, B100, B001, B000, B100, 1,
113   B010, B000, B010, B010, B000, B010, B010, B000, B010, 1,
114   B100, B000, B001, B100, B000, B001, B100, B000, B001, 1,
115   B000, B101, B000, B000, B101, B000, B000, B101, B000, 1,
116   B001, B000, B100, B001, B000, B100, B001, B000, B100, 1,
117   B010, B000, B010, B010, B000, B010, B010, B000, B010, 1,
118   B100, B000, B001, B100, B000, B001, B100, B000, B001, 1,
119   B000, B101, B000, B000, B101, B000, B000, B101, B000, 1,
120   B001, B000, B100, B001, B000, B100, B001, B000, B100, 1,
121   B010, B000, B010, B010, B000, B010, B010, B000, B010, 1,
122   B100, B000, B001, B100, B000, B001, B100, B000, B001, 1,
123   B000, B101, B000, B000, B101, B000, B000, B101, B000, 1,
124   B001, B000, B100, B001, B000, B100, B001, B000, B100, 1,
125   B010, B000, B010, B010, B000, B010, B010, B000, B010, 1,
126
127
128   // Little cube to big cube
129   B000, B000, B000, B000, B011, B011, B000, B011, B011, 10,
130   B111, B111, B111, B111, B111, B111, B111, B111, B111, 10,
131   B000, B000, B000, B000, B011, B011, B000, B011, B011, 5,
132   B000, B000, B000, B000, B000, B000, B000, B000, B001, 2,
133   B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
134   B111, B111, B111, B111, B111, B111, B111, B111, B111, 2,
135   B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
136   B000, B000, B000, B000, B000, B000, B000, B000, B001, 2,
137   B000, B000, B000, B000, B011, B011, B000, B011, B011, 2,
138   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
139   B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
140   B000, B000, B000, B000, B000, B000, B000, B000, B001, 1,
141   B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
142   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
143   B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
144   B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
145   B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
146   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
147   B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
148   B000, B000, B000, B000, B000, B000, B000, B000, B001, 1,
149   B000, B000, B000, B000, B011, B011, B000, B011, B011, 1,
150   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
151   B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
152   B100, B000, B000, B000, B000, B000, B000, B000, B000, 1,
153   B110, B110, B000, B110, B110, B000, B000, B000, B000, 1,
154   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
155   B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
156   B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
157   B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
158   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
159   B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
160   B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
161   B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
162   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
163   B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
164   B000, B000, B001, B000, B000, B000, B000, B000, B000, 1,
165   B000, B011, B011, B000, B011, B011, B000, B000, B000, 1,
166   B111, B111, B111, B111, B111, B111, B111, B111, B111, 1,
167   B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
168   B000, B000, B000, B000, B000, B000, B100, B000, B000, 1,
169   B000, B000, B000, B110, B110, B000, B110, B110, B000, 1,
170
171   // Diagonal wipe, starting in the center
172   B111, B111, B111, B111, B111, B111, B111, B111, B111, 5,
173   B111, B111, B111, B111, B111, B111, B111, B101, B111, 1,
174   B111, B111, B111, B111, B101, B111, B111, B101, B111, 1,
175   B111, B111, B111, B111, B101, B111, B111, B100, B111, 1,
176   B111, B101, B111, B111, B100, B111, B111, B100, B110, 1,
177   B111, B101, B111, B111, B100, B111, B111, B100, B110, 1,
178   B111, B011, B111, B111, B100, B110, B111, B100, B100, 1,
179   B111, B100, B110, B111, B100, B100, B111, B100, B000, 1,
180   B111, B100, B100, B111, B100, B000, B111, B000, B000, 1,
181   B111, B100, B000, B111, B000, B000, B011, B000, B000, 1,
182   B111, B000, B000, B011, B000, B000, B001, B001, B000, 1,
183
184   // A 2-LED wide diaginal stripe that orbits the cube
185   B011, B000, B000, B001, B001, B000, B000, B001, B001, 1,
186   B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
187   B000, B001, B001, B000, B000, B011, B000, B000, B110, 1,
188   B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
189   B000, B000, B110, B000, B100, B100, B100, B100, B000, 1,
190   B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
191   B100, B100, B000, B110, B000, B000, B011, B000, B000, 1,
192   B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
193   B011, B000, B000, B001, B001, B000, B000, B001, B001, 1,
194   B001, B001, B000, B000, B001, B001, B000, B000, B011, 1,
195   B000, B001, B001, B000, B000, B011, B000, B000, B110, 1,
196   B000, B000, B011, B000, B000, B110, B000, B100, B100, 1,
197   B000, B000, B110, B000, B100, B100, B100, B100, B000, 1,
198   B000, B100, B100, B100, B100, B000, B110, B000, B000, 1,
199   B100, B100, B000, B110, B000, B000, B011, B000, B000, 1,
200   B110, B000, B000, B011, B000, B000, B001, B001, B000, 1,
201
202   //Pause
203   B000, B000, B000, B000, B000, B000, B000, B000, B000, 10,
204 };
205
206
207 const int cubeSize=3;   // The dimensions of the cube, in LEDs
208 const int planeSize=9;  // The number of LEDs on each plane of the cube 
209 const int planeDisplayTime=1000; // The time each plane is displayed in microseconds
210 const int updateSpeed=100; // Multiplier for displayTime to get milliseconds
211
212 byte patternBuffer[planeSize]; // Stores the current pattern from patternData
213 int patternIndex; // Keeps track of the line of the pattern being displayed
214 int patternBufferIndex; // Counts where we are while painting the display
215 byte displayTime; // Multiplied by 100ms to set the frame duration
216 unsigned long endTime; // Tracks when we are finished with the frame
217
218 int ledrow; // Counts LED rows in the refresh loop
219 int ledcol; // Counts LEDs columns in the refresh loop
220 int ledpin; // Counts LEDs in the refresh loop
221
222 // Defining pins in array makes it easier to access them in the program
223 // and change how they are wired up, if necessary.
224
225 int LEDPin[] = {2,3,4,5,6,7,8,9,10};
226 int PlanePin[] = {14,15,16};
227
228 void setup()
229 {
230   // set up LED pins as output (active HIGH)
231   for (int i=0; i<planeSize; i++) {
232     pinMode(LEDPin[i], OUTPUT);
233   }
234   // set up plane pins as outputs (active LOW)
235   for (int i=0; i<cubeSize; i++) {
236     pinMode(PlanePin[i], OUTPUT);
237   }
238 }
239
240 // display pattern in table until displayTime is zero (then repeat)
241 void loop()
242 {
243   // Initialize patternIndex to the beginning of the pattern data table
244   patternIndex = 0;
245   // Loop over entries in pattern data table while the displayTime>0
246   do {
247     // memcpy is copies the data from the Program Memory (PROMGMEM) into a temporary array buffer
248     // called pattern buffer. This will be used to determine what to light up
249     memcpy_P( patternBuffer, patternData+patternIndex, planeSize );
250     // The size of the pattern index is incremented by 9, which keeps track of 
251     // where we are getting our data from in the pattern Buffer.
252     // It will be reset back to 0 after all three planes are displayed.
253     patternIndex += planeSize;
254     // Read the displayTime from PROGMEM and increment the pattern index to get the right values.
255     // The displayTime is every 10th data element.
256     displayTime = pgm_read_byte_near( patternData + patternIndex++ );
257     // Calculate the endTime from the current time (ms) and the displayTime 
258     endTime = millis() + displayTime * updateSpeed;
259     
260     // loop while displayTime>0 and current time < endTime
261     while ( millis() < endTime ) {
262       patternBufferIndex = 0; // reset index counter to beginning of buffer
263
264       // Loop over the planes of the cube
265       for (int plane=0; plane<cubeSize; plane++) {
266         // Turn the previous plane off
267         if (plane==0) {
268           digitalWrite(PlanePin[cubeSize-1], HIGH);
269         } 
270         else {
271           digitalWrite(PlanePin[plane-1], HIGH);
272         }
273
274         // Prepare the digital pins to light up LEDs
275         ledpin = 0;
276         for (ledrow=0; ledrow<cubeSize; ledrow++) {
277           for (ledcol=0; ledcol<cubeSize; ledcol++) {
278             // the binary values in the ledcol variable are shifted left by 1 bit, indicated by: "1 <<"
279             // The & is a bitwise AND. If both patternBuffer and the new value coming in from ledcol
280             // are 1, the resulting output is HIGH, otherwise the output is LOW.
281             // ledpin++ simply goes to the next LEDPin in the list.
282             digitalWrite( LEDPin[ledpin++], patternBuffer[patternBufferIndex] & (1 << ledcol) );
283
284           }
285           patternBufferIndex++;
286
287         }
288
289         // turn current plane on
290         digitalWrite(PlanePin[plane], LOW);
291         // delay planeDisplayTime us
292         delayMicroseconds(planeDisplayTime);
293       }
294     } // End of the while loop
295   } 
296   while (displayTime > 0); // read patterns until time=0 which signals end
297 }
298
299