a-v led cube final report
TRANSCRIPT
-
7/28/2019 A-V LED Cube Final Report
1/42
Audio Visual LED Cube
ECE 791/792 Final ReportTeam Members: Matthew Daigle, Robert Hunter, Kendra Kreider
Advisor: Dr. Richard Messner
Date: May 2011
-
7/28/2019 A-V LED Cube Final Report
2/42
D a i g l e , H u n t e r , K r e i d e r | 2
Acknowledgments
This projects realization is due in part to the sponsorship granted from Raytheon as well as the
funding provided by the University of New Hampshire. Special thanks go out to both of these
organizations for providing us with the freedom to pursue our own project and their full support along
the way. The A/V LED team would also like to acknowledge the support of Dr. Richard Messner, whos
push for us to stay on track, as well as his intrigue and excitement for the project, really allowed the A/V
LED cube to be the best possible project it could be.
Project Team
From left to right: Matthew Daigle, Robert Hunter, Kendra Kreider, Professor R. Messner
-
7/28/2019 A-V LED Cube Final Report
3/42
D a i g l e , H u n t e r , K r e i d e r | 3
Abstract
The goal of this project was to create a three dimensional 5x5x5 array of RGB LEDs powered by
the Arduino microcontroller. This array of LEDs creates a cube shape that, with simple C programming,
can display full color visual images through the use of multiplexing and serial in, parallel out shift
registers. The cube can also produce visual effects that correspond to an audio input in real time
through the use of the MSGEQ7 integrated circuit, which is a seven-band graphic equalizer IC.
The cube also has commercial potential due to its unique and interesting design, though not at
its current cost of construction. All design goals were met for this project, and future improvement will
most likely consist of interactivity between the cube and the user.
-
7/28/2019 A-V LED Cube Final Report
4/42
D a i g l e , H u n t e r , K r e i d e r | 4
Table of Contents
INTRODUCTION ...................................................................................................................................................... 5
REACHING FINAL DESIGN.................................................................................................................................... 6
BUILD ......................................................................................................................................................................... 7
LEDMATRIX ............................................................................................................................................................................ 7
CASING....................................................................................................................................................................................... 8
CIRCUIT DESIGN ..................................................................................................................................................... 9
ARDUINO ................................................................................................................................................................................... 9
MUSIC CHIP ............................................................................................................................................................................ 10
SHIFT REGISTERS ..................................................................................................................................................................12
GROUND TRANSISTORS ........................................................................................................................................................ 13
TESTING .................................................................................................................................................................................. 14
SOFTWARE ............................................................................................................................................................ 14
DESIGN ISSUES ..................................................................................................................................................... 17
FUTURE WORK .................................................................................................................................................... 18
APPENDIX I: PROJECT PHOTOS...................................................................................................................... 21
APPENDIX II: EXAMPLE LIGHTSHOW .......................................................................................................... 28
APPENDIX III: EXAMPLE MUSIC SHOW ....................................................................................................... 36
-
7/28/2019 A-V LED Cube Final Report
5/42
D a i g l e , H u n t e r , K r e i d e r | 5
Introduction
Light organs have been a popular Do-It-Yourself electrical engineering design ever since their
implementation in the 1970s. In their most basic design, light organs consisted of three lights: one to
show low frequencies, one to show midrange frequencies, and one to show high frequencies. As
technologies have advanced, improvements in this basic design have been made such as displaying the
frequencies over two-dimensional banners as well as being able to select a greater number of
frequencies to display.
This project takes the simple concepts of light organs and electronic banners and builds off of
them to create an LED light organ in three dimensions. This audio-visual LED cube (3D LED light organ)
consists of a 5x5x5 array of RGB LEDs that is able to display low-resolution images as well as interact
with different frequencies of an audio input through the use of an audio-equalizer chip. The primary
hardware design goal was to come up with a way to control all 125 LEDs (each with 4 leads that needed
individual control) using the least amount of wires and components necessary but without sacrificing
performance and controllability of the cube. The software design aspect of this project consisted of
creating visually appealing light and music animations. Hypothetically, this project has no definitive
endpoint. An endless number of animations can be created, and a cleaner user interface could also be
continuously developed. The LED cube is a viable commercial product with limitless potential in design
applications.
-
7/28/2019 A-V LED Cube Final Report
6/42
D a i g l e , H u n t e r , K r e i d e r | 6
Reaching Final Design
The final project design was a 5x5x5 RGB LED cube. The size of this finished product was decided
mostly due to cost of LEDs. To reach this final goal, incremental steps were first taken to gain familiarity
with the design and coding. The first step of this project was to gain the basic tools and knowledge to
build an RGB cube by first building a simpler size 3x3x3 single color LED cube. Although the 3x3x3 cube is
more simplistic, there were many design similarities between it and larger cubes. Building this allowed
us to foresee some problems with a larger-scale design and it also made coding simpler, which made the
process of learning how to use the microcontroller easier and quicker. Figure 1 below shows the
complete 3x3x3 single color cube connected to the microcontroller.
Figure 1. Initial 3x3x3 Design
-
7/28/2019 A-V LED Cube Final Report
7/42
D a i g l e , H u n t e r , K r e i d e r | 7
Build
Figure 2. Block Diagram of Project
LED Matrix
The LED matrix consists of 125-RGB LEDs, which are arranged in a 5x5x5 array. Each of the 5
layers (or floors) is made from 25 LEDs. All of the LEDs in a layer share a common ground, which is
connected using 1/16 copper rodding. The copper rods give the lattice its rigidity making the
structure stronger and sturdier.
A single vertical column of LEDs is connected with 3 sub-columns for the red, green, and blue
anodes. The number of columns, therefore, totals to 75 (25 LED columns x 3 sub-columns = 75 total
columns). The anodes for each respective color in a column of LEDs are connected using single strands
of bare copper wire. You will also notice that 5 columns are connected using the 1/16 copper rods. This
was done, again, to add strength to the lattice. A single LED is addressed by applying 5V to one of the 75
columns and then grounding one of the 5 layers, which completes a circuit for only one LED so only one
LED will be turned on (shown in Figure 3).
At the bottom of the cube, you will see that magnet wire was used to connect the 75 columns to
the circuitry inside of the wooden base. Magnet wire was chosen because it has a thin enamel coating
-
7/28/2019 A-V LED Cube Final Report
8/42
-
7/28/2019 A-V LED Cube Final Report
9/42
D a i g l e , H u n t e r , K r e i d e r | 9
On the back of the wooden base, there are 4 ports DC In, USB In, Audio In, and Audio Out. The
audio input accepts audio from any device that uses a 3.5mm audio jack (i.e. computer, iPod, phone).
The audio output also uses a 3.5mm audio jack, but should only be connected to speakers that have an
independent power supply. Connecting headphones or speakers that are without an independent power
supply will load down the audio circuit. This, in turn, affects the audio-visualization lightshow
performance. The DC input supply powers the Arduino microcontroller. The Arduino itselfpowers the
LEDs in the cube. A 2.1mm, center-positive, 12 V, 1A rated AC adapter is the minimum current rating
that should be used due to the current necessary to drive the electronics. The USB input can also be
used to power the microcontroller when an AC adapter is not available. Although the USB can be used
to power the microcontroller the USB port is normally used just to upload the lightshow sketches to the
microcontroller from a computer using the Arduino application.
In order to protect the cube a plexiglass case was constructed to cover the lattice. This was done
purely for the protection of the fragile cube of LEDs andother cases could also be made from different
types of glass or plexiglass that might give off different lighting effects from the light emanating from
the cube.
All pictures relating to the build process as well as how the cube was tested are provided in
Appendix 1.
Circuit DesignArduino
The Arduino UNO is the microcontroller board that is used to control the input of information to
the shift registers, music chip, and ground transistor array. In total, 11 of the digital input/output pins
are used as well as 1 of the 6 analog input pins. Along with these pins the Arduino UNO has a 16MHz
-
7/28/2019 A-V LED Cube Final Report
10/42
D a i g l e , H u n t e r , K r e i d e r | 10
crystal oscillator, USB jack, power jack, ICSP header, and a reset button. The USB jack is used to upload
programs written on a computer to the Arduino and will also provide power to the board. If the user
plans on using just one sketch, that sketch can be uploaded to the board and only the power jack is then
necessary to power the LED cube.
For this project the Arduino UNO is the heart of the LED Cube. Light shows are programmed
using C coding and uploaded to the board to be sent out serially to the shift registers. The Arduino can
also read in the analog data processed from the MSGEQ7 chip, which can then be manipulated in a
lightshow sketch. This process is used to create the real-time audio-visual lightshows.
The final circuit design for the LED cube can be split in to three significant portions (shown in
Figure 4): the music chip to allow for audio analysis (1), the serial-in, parallel-out shift registers to
control each column of LEDs (2), and the transistor circuit used to ground each individual layer (3).
Music Chip
The MSGEQ7 is a seven-band graphic equalizer integrated circuit that divides an audio signal
into frequency bands. These seven bands are split over the range of audible frequencies and are located
at 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25kHz, and 16kHz. Since one face of the cube has a 5x5
2
3
1
Figure 4. Three Major Circuit Elements in Cube
-
7/28/2019 A-V LED Cube Final Report
11/42
D a i g l e , H u n t e r , K r e i d e r | 11
resolution, five of the seven frequencies were used, excluding the 1kHz and 16kHz frequency bands, for
most of the audio-visual programming. These two frequencies were omitted since they tended not to be
very predominant in most of the songs that were chosen. The MSGEQ7 serially samples one frequency
at a time, and returns the amplitude of the sampled frequency to the Arduino. An amplitude range of 0
to 400 was consistently returned to the Arduino, which was then scaled down by 80 to result in values
between 0 and 5, as the bar-height at each frequency would only range from 0 to 5 LEDs. The frequency
bands were displayed on the front face of the cube where a vertical column of LEDs represented one of
the five frequencies, and the height of the column represented the amplitude of a frequency. The pin
diagram of the MSGEQ7 setup is shown below in Figure 5.
Figure 5. Pin Diagram for MSGEQ7
-
7/28/2019 A-V LED Cube Final Report
12/42
D a i g l e , H u n t e r , K r e i d e r | 12
Shift Registers
The 74HC595 8-bit serial-in, parallel-out shift registers were ultimately used as the way to
address the LED matrix from the Arduino microcontroller. The setup for these shift registers is based on
the 75 columns discussed earlier. Each of the 75 columns is connected to the output pin of a shift
register, and each shift register has 8 output pins, therefore 10 shift registers are needed in total
(leaving 5 pins disconnected). All bits are sent from the Arduino to the shift registers using a sendOut()
command which serially sends out 8 bits at a time; repeating this action 9 more times will result in the
shift registers being completely filled with the necessary information for a single layer of an image (an
image being comprised of the 5 layers of the cube). The registers latch pins are then turned on, which
sends out the information in the shift registers in parallel to each column and turns on the
corresponding LEDs.
The shift registers are organized in sections of 25 columns: first the necessary blue LED bits are
sent in, then the 25 green LED bits are sent, and finally the 25 red LED bits are sent before the latch pins
are triggered. This design minimizes the number of output pins needed by the microcontroller, as all of
the information sent to the LED matrix is output through just one pin on the Arduino. If this design was
utilized there would not have been enough pins on the Arduino to control all 75 columns of the LED
matrix. The functional diagram for the 74HC595 is shown below in Figure 6.
Q0 Q7 are the parallel outputs that are connected to the LED matrix, Q7 is the serial output to
allow for multiple shift registers to be cascaded together (which is how all ten shift registers are written
using only one output pin on the Arduino), DS is the serial data input read from the Arduino, SHCP is the
shift register clock input (serial input shift clock), STCP is the storage register clock input (parallel output
latch) which controls when the bits are sent out, MR (master reset) clears the shift registers, and OE
(output enable) is always set to on as an active LOW.
-
7/28/2019 A-V LED Cube Final Report
13/42
D a i g l e , H u n t e r , K r e i d e r | 13
Figure 6. Functional Diagram for 74HC595
Ground Transistors
The third and final aspect of the circuit board is the most basic, and consists of five transistors
acting as switches to allow each layer to be individually connected to ground. For the transistors the
LM3046 Transistor Array IC was used as it consists of five matched transistors in one IC, which keeps the
current consistent for all layers (maintaining even luminosity for each layer). Five output pins from the
Arduino are used to turn on the individual transistors. Providing a 5V signal to the base of one of the five
transistors turns on the switch which connects the respective layer to ground (shown in Figure 7). The
five layers are shifted through one at a time to allow for multiplexing on the cube as the shift registers
can only hold the information for one layer at a time.
-
7/28/2019 A-V LED Cube Final Report
14/42
-
7/28/2019 A-V LED Cube Final Report
15/42
D a i g l e , H u n t e r , K r e i d e r | 15
each layer has a common ground, LEDs in two different columns and two different layers cannot be lit
up without additional, unwanted LEDs also lighting. Figure 8 displays the ideal case versus what happens
in reality when two columns and two layers are turned on at the same time. To avoid this issue, all layers
need to be multiplexed through at a frequency greater than or equal to 60Hz. Therefore, each ground
layer can be lit for up to of 3.33 milliseconds before the next layer must turn on. At this rate, persistence
of vision keeps the human eye from noticing any flicker that occurs from the layers turning on and off.
Figure 8. Ideal vs. Real interpretation of Cube Without Multiplexing
Multiplexing is also necessary to display colors other than red, green, or blue. For example,
switching between red and blue will display purple from the LED. Different shades of purple can also be
made depending on the ratio of how long one color is on relative to the other. Any combination of the
three basic colors, red, green, and blue, can be used to create another color. As mentioned before, the
-
7/28/2019 A-V LED Cube Final Report
16/42
D a i g l e , H u n t e r , K r e i d e r | 16
switching between the two or three basic colors must be at a rate faster than the 60Hz so that flickering
is not noticeable.
This concept of creating color with multiplexing is combined with the concept of multiplexing
ground layers to create an image. Each color has to be split into a total interval of less than 3.33
milliseconds. To make the color more cohesive, the two separate colors should be flashed twice within
this time. So to create purple, the red should be turned on for 750 microseconds, then blue for 750
microseconds, and then repeat that process one more time. The registers and other components also
have delays of their own, so the actual time each color can be turned on for is further reduced. Since the
colors are being multiplexed so quickly, the brightness of the LED is dependent on how long a color stays
on before being turned off. Although multiplexing faster disperses the colors more evenly within the
LED, it also reduces how bright the mixed color is, which is not ideal.
When creating a lightshow, a certain amount of artistic creativity is necessary, and you must
also be able to apply the concepts of multiplexing the layers and multiplexing the colors to realize the
image accurately and efficiently. Combing the two is not without its difficulties. To simplify the process,
it is better to program the basic animation in a single color first, and then add color to the design once
the animation is in working order.
Audio-visualization lightshows were programmed in the same manner that a regular animation
was programmed along with the use of the MSGEQ7 seven-band graphic equalizer chip. The amplitudes
of the frequency bands of an audio input are sent to the Arduino microcontroller, which were then
manipulated within the lightshow program. Audio-visualization lightshows are, therefore, frequency and
amplitude dependent.
-
7/28/2019 A-V LED Cube Final Report
17/42
D a i g l e , H u n t e r , K r e i d e r | 17
Design Issues
Difficulty, time, budget, and experience were all contributing factors to the design issues.
Throughout the course of the project there were some aspects of design that did not end up working
out as effectively or as efficiently as our initial design had intended, but more efficient ways of building
and programming were discovered as more knowledge of the cube was gained.
Even though there were many minor changes implemented over the course of the project, there
were really only three significant design issues that arose. The first issue was a matter of design
simplification. The initial design for the A/V LED cube involved the Arduino using 2-to-4 decoders in
order to communicate with the LED matrix. Initially, the largest Arduino (Mega 2560) had enough output
pins to run the cube using 2-to-4 decoders, but with the implementation of the music functionality this
ended up no longer being the case. This issue was resolved by using 8-bit SIPO shift registers (10 of
them) that could read in data from serially through one output pin on the Arduino. The final design
ended up using a total of 12 output pins on the Arduino, which allowed the cube to be built with a
smaller and less expensive microcontroller the Arduino Uno.
The second design issue occurred when the audio visualization was first tested on the final cube.
When speakers or headphones were plugged into the circuit for audio output, it ended up loading down
the audio circuit so that the amplitudes of the frequencies being sampled were read as being half of
what they actually were. This was due to the fact that the speakers acted as a voltage divider and
reduced the voltage of the audio signal that was being fed into the MSGEQ7s input pin. Initially, buffer
circuits and simple audio amplifiers were created to try to fix the problem, however the quality of the
audio being output through the speakers was significantly deteriorated. Eventually the cube was tested
using speakers that were powered with an independent power supply. This kept the speakers from
drawing any power from the cubes audio circuit and completely solved the issue of the speakers
-
7/28/2019 A-V LED Cube Final Report
18/42
D a i g l e , H u n t e r , K r e i d e r | 18
loading down the visual effects on the cube. It also helped to simplify the final circuit design as no
amplifiers or buffers were needed.
The last major change in the final design was implemented mostly to save time and to simplify
the wiring and soldering of the final circuit. Initially, the thin copper wires connecting the columns were
to be fed through the top of the wooden box, soldered to 22 AWG insulated wire, and then cut to length
and soldered to the perforated board. This would have been a very time consuming and tedious process.
And not only that, but the joints between the copper wire and the insulated wire would have been very
weak and frail. Through some research, magnet wire was decided to be the best viable option. Magnet
wire is a thin wire (28 AWG was used in the project) with a very thin enamel coating that burns off when
soldered. Using such thin wire also reduced the amount of space needed inside the box to hold all of the
wire. 22 AWG wire along with its plastic insulation is considerably thicker than 28 AWG wire, and took
up most of the available space inside the wooden box. The enameled wire was soldered directly to the
bottom layer of the cube, fed through the box, and then fed through the perforated board. Once all of
the wires were through the circuit board, they could then be pulled tight, soldered to the board, and
finally trimmed.
Future Work
This project focused primarily on the most efficient way to build an LED cube and to also
interface music with the cube. The cube was designed with simplicity in mind, so there is a lot room for
development of both the hardware and the software. This section outlines a few of the possibilities for
work on this as well as future LED cube projects.
In terms of hardware, this cube was built to simply function as a 5x5x5 matrix of LEDs. While this
build was stationary, rotational effects could be implemented using motors and more loose fitted LEDs
-
7/28/2019 A-V LED Cube Final Report
19/42
D a i g l e , H u n t e r , K r e i d e r | 19
(in terms of wiring). Accelerometers could also be utilized in such applications. Also, the only visual
effects being generated by this LED cube are from the LEDs themselves. Things such as one-way mirrors,
lasers, light bulbs, smoke machines, and even dry ice have all been suggested over the course of this
year. With most of the budgeted time going into research, most of these ideas could not be realized in
this project, however a future project that already has the design specifications implemented in this
build could develop this project even further.
Improvement in software design is really where a lot of future work could be spent. While this
team focused purely on creating light shows for display and the ability to detect and play an audio signal
in real time, these are not the only possible ways in which to use the LED cube. One aspect the team
started to touch on near the end of the project was user interactivity. Through the use of a serial
monitor built in to the Arduino software, the microcontroller can serially read in inputs from the
keyboard and use these inputs to execute specific code already uploaded to the Arduino. This was used
to switch between the animations and audio-visualization shows during the URC presentation, but the
idea can be expanded in other ways.
One application that the group started to explore was programming user-interactive games. The
low resolution of the cube has its limitations, but games such as 3D Snake or 3D Pong would greatly
expand the current functionality of the LED cube into something more than just a light organ.
The cube could also be used to simulate 3D models such as earthquakes, fluids, or cellular
automation. Again, however, the low resolution of the cube would not allow for models that are
extremely detailed and complex, so a larger single colored cube would most likely be a better build if
such applications were to be implemented.
Improvements could also be made on how the animations are coded and that also expand on
the idea of user interactivity. Simply put, this teams method for coding the cube may not have been the
-
7/28/2019 A-V LED Cube Final Report
20/42
D a i g l e , H u n t e r , K r e i d e r | 20
most efficient or easiest way to achieve the light and music shows. While explicitly writing the binary
values into an array for each color was very intuitive and straightforward, it required a lot of abstract
thinking to properly turn on and off each LED for each desired image.
The most interesting solution to this problem, and a solution that opens up coding the cube to
everyone and not just programmers, is to create a graphic user interface, or GUI, to visually program the
cube. By having a model of the cube on a computer, the user would be able to choose a color and then
click the LEDs that they wanted to turn on with that color and then save the image for use in the actual
visual display. The user would then move on to programming the next image until eventually they have
a complete light show finished in a fraction of the time it would take to program it individually. While it
would take a very long time to actually program the GUI to be streamlined and bug free, it would save a
lot of time in the long run. This type of interface would also eliminate the need for the common user to
have a substantial knowledge of programming. The GUI would reduce programming the cube down to
simply creating an animation visually, which would again add to the cubes commercial viability.
-
7/28/2019 A-V LED Cube Final Report
21/42
D a i g l e , H u n t e r , K r e i d e r | 21
Appendix I: Project Photos
-
7/28/2019 A-V LED Cube Final Report
22/42
D a i g l e , H u n t e r , K r e i d e r | 22
-
7/28/2019 A-V LED Cube Final Report
23/42
D a i g l e , H u n t e r , K r e i d e r | 23
-
7/28/2019 A-V LED Cube Final Report
24/42
D a i g l e , H u n t e r , K r e i d e r | 24
-
7/28/2019 A-V LED Cube Final Report
25/42
D a i g l e , H u n t e r , K r e i d e r | 25
-
7/28/2019 A-V LED Cube Final Report
26/42
D a i g l e , H u n t e r , K r e i d e r | 26
-
7/28/2019 A-V LED Cube Final Report
27/42
D a i g l e , H u n t e r , K r e i d e r | 27
-
7/28/2019 A-V LED Cube Final Report
28/42
D a i g l e , H u n t e r , K r e i d e r | 28
Appendix II: Example Lightshow//Diagonals
//pattern starts at lower corner
//and travels up to opposite diagonal corner
//pattern fades from blue on bottom layer to pink on top layer
//code was edited to randomly select the starting corner
//code was edited to randomly select whether pattern travels up or down
//initializing variables for ground & register connects to arduino
int dataPin = 13; //Serial Data Input
int latchPin = 12; //Parallel Output Clock
int clockPin = 11; //Shifting Clock
int regResetPin = 10; //Shift Register Clear
int ground[] = {
9, 8, 7, 6, 5}; //5 Ground Layers
//variables used to implement design
int count=0;
int totalDelay=0;
int delayT=300; //delay
int corner=1; //random variable that picks corner
int upDown=1; //variable determines if design is traveling up or downint numLED=1; //number of LEDs in diagonal
int incLED=1; //variable that determines if diagonal size is increasing or decreasing
int colorNum=1;
byte data;
byte dataArray[10];
int zeros[25] = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
int ones[25] = {
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1
};
int layer0[25] = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
int layer1[25] = {0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
int layer2[25] = {
0,0,0,0,0,
0,0,0,0,0,
-
7/28/2019 A-V LED Cube Final Report
29/42
D a i g l e , H u n t e r , K r e i d e r | 29
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
int layer3[25] = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
int layer4[25] = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
};
//setup- tells Arduino which pins are outputs, etc
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(regResetPin, OUTPUT);
pinMode(ground[0], OUTPUT);
pinMode(ground[1], OUTPUT);
pinMode(ground[2], OUTPUT);
pinMode(ground[3], OUTPUT);
pinMode(ground[4], OUTPUT);
analogReference(DEFAULT);
digitalWrite(regResetPin, 0); //Clear the shift registers
digitalWrite(regResetPin, 1);
Serial.begin(1500000);
turnOffLEDs(5);
}//End setup
void loop() {
corner=random(1,5); //choose random corner from 1-4
upDown=random(2); //choose if design travels up or down, 0 or 1
while(count
-
7/28/2019 A-V LED Cube Final Report
30/42
D a i g l e , H u n t e r , K r e i d e r | 30
else if (i==3){
colorIt(layer3,colorNum+3,delayT,i);
}
else if (i==4){
colorIt(layer4,colorNum+4,delayT,i);
}
totalDelay=totalDelay+1;
}
}
count++; //count pattern increment
if(numLED==5){
incLED=0;
}
if (incLED){
numLED++;
}
else {
numLED--;
}
totalDelay=0;
}
count=0;
incLED=1;
numLED=1;
}//End loop
//////////////////////////////// FUNCTIONS //////////////////////////////////
/* This function places the 1x25 binary array into a 1x80
(10 registers x 8 pins = 80 bits) binary array. These 80 binary values
are then converted into a 1x10 byte array of HEX values */
void convert(int tempArray[25], char color, byte byteArray[10]) {
int eightyArray[80];
/* Place the 1x25 binary array into the 1x80 binary array. The location of
the 25 values in the 1x80 array is determined by what color the arrayis. First 25 values are reserved for blue, second 25 for green, third
25 for red, and the last 5 values are don't cares. Only one color will
be on at a time. */
//Blue
if(color == 'b') {
for(int i = 0; i < 25; i++) {
eightyArray[i] = tempArray[i];
}
for(int j = 25; j < 80; j++) {
eightyArray[j] = 0;
}
}
//Green
else if(color == 'g') {
for(int i = 0; i < 25; i++) {eightyArray[i] = 0;
}
for(int j = 25; j < 50; j++) {
eightyArray[j] = tempArray[j - 25];
}
for(int k = 50; k < 80; k++) {
eightyArray[k] = 0;
}
}
//Red
-
7/28/2019 A-V LED Cube Final Report
31/42
D a i g l e , H u n t e r , K r e i d e r | 31
else if(color == 'r') {
for(int i = 0; i < 50; i++) {
eightyArray[i] = 0;
}
for(int j = 50; j < 75; j++) {
eightyArray[j] = tempArray[j - 50];
}
for(int k = 75; k < 80; k++) {
eightyArray[k] = 0;
}
} //Red
/* Now convert the 80 bits into 10 bytes and store them in byteArray,
which points to dataArray */
int LSB = 0; //Represents least significant bit of the 8 bits being converted
int MSB = 7; //Represents most significant bit of the 8 bits being converted
int conversionArray[8]; //Array used to store the 8 bits being converted
int byteIndex = 0; //Used to index the byteArray
int indexA = 0;
while(MSB < 80) {
indexA = 0;
for(int i = LSB; i
-
7/28/2019 A-V LED Cube Final Report
32/42
D a i g l e , H u n t e r , K r e i d e r | 32
if(binary[7] == 1) {
sum = sum + 0x01;
}
return sum;
}//End binaryToByte
///////////////////////////////////////////////////////////////////////////////////
//This function writes the array values to the registers and sends them to the cube
void sendOut() {
digitalWrite(latchPin, 0); //Ground latch pin until done shifting in all data
for(int i = 0; i < 10; i++) {
data = dataArray[i];
shiftOut(dataPin, clockPin, MSBFIRST, data); //Shift in the data one byte at a
time
}
digitalWrite(latchPin, 1); //Send out the data from the registers
}//End sendOut
///////////////////////////////////////////////////////////////////////////////////
void turnOffLEDs(int reset) {
if (reset==5){ //turn all five grounds off
for(int k = 0; k < 5; k++) {
digitalWrite(ground[k], 0);
}
}
else if (reset>=0 && reset
-
7/28/2019 A-V LED Cube Final Report
33/42
D a i g l e , H u n t e r , K r e i d e r | 33
int adrs=0;
if(crner==1){
adrs=a1[cnt];
for(int j=0;j
-
7/28/2019 A-V LED Cube Final Report
34/42
D a i g l e , H u n t e r , K r e i d e r | 34
adrs=adrs+6;
}
}
else if(crner==4){
adrs=a4[cnt];
for(int j=0;j
-
7/28/2019 A-V LED Cube Final Report
35/42
D a i g l e , H u n t e r , K r e i d e r | 35
dRed=delayTime*50/100;
dGreen=delayTime*50/100;
dBlue=0;
}
else if(colorNum==10){//30red-70green
dRed=delayTime*30/100;
dGreen=delayTime*70/100;
dBlue=0;
}
else if(colorNum==11){//green
dGreen=delayTime;
dBlue=0;
dRed=0;
}
else if(colorNum==12){//80green-20blue
dGreen=delayTime*80/100;
dBlue=delayTime*20/100;
dRed=0;
}
else if(colorNum==13){//50green-50blue (cyan)
dGreen=delayTime*50/100;
dBlue=delayTime*50/100;
dRed=0;
}
else if(colorNum==14){//20green-80blue
dGreen=delayTime*20/100;
dBlue=delayTime*80/100;
dRed=0;
}
else{
dBlue=delayTime;
dRed=0;
dGreen=0;
}
if(dBlue!=0){
convert(pattern, 'b', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube (5 frames makes one image)digitalWrite(ground[gg], 1);
delayMicroseconds(dBlue); //time blue is on
turnOffLEDs(gg);
}
if(dRed!=0){
convert(pattern, 'r', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube (5 frames makes one image)
digitalWrite(ground[gg], 1);
delayMicroseconds(dRed); //time red is on
turnOffLEDs(gg);
}
if(dGreen!=0){
convert(pattern, 'g', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube (5 frames makes one image)
digitalWrite(ground[gg], 1);delayMicroseconds(dGreen); //time green is on
turnOffLEDs(gg);
}
}//End colorIt
-
7/28/2019 A-V LED Cube Final Report
36/42
D a i g l e , H u n t e r , K r e i d e r | 36
Appendix III: Example Music Show//Front Face Audio
//Basic music program lights only the front face
//Each of the five columns is a different frequency
//the leftmost column displays bass and freqeuncy gets higher traveling right
//the audio signal is sampled and filtered into frequency ranges//the corresponding freqeuncy column lights up with an amplitude of 0-5 LEDs
//depending on audio sample
//program sets base for other music programs
int dataPin = 13; //Serial Data Input
int latchPin = 12; //Parallel Output Clock
int clockPin = 11; //Shifting Clock
int regResetPin = 10; //Shift Register Clear
int ground[] = {
9, 8, 7, 6, 5}; //5 Ground Layers
int analogPin = A0; //Specrtum Analyzer Analog Output (frequency's amplitude)
int strobePin = 4; //Specrtum Analyzer Strobe (read next frequency value)
int msgResetPin = 3; //Specrtum Analyzer Clear
int spectrum[7]; // Spectrum analyzer read values will be kept here
//intialize variables
int blue[25];
int green[25];
int red[25];
byte data; //Holds one byte at a time for writing to the dataArray
byte dataArray[10]; //Holds the 10 bytes to write to the registers
int t = 250; //Delay time constant (in microseconds)
int i;
int eightyArray[80];
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(regResetPin, OUTPUT);pinMode(ground[0], OUTPUT);
pinMode(ground[1], OUTPUT);
pinMode(ground[2], OUTPUT);
pinMode(ground[3], OUTPUT);
pinMode(ground[4], OUTPUT);
pinMode(analogPin, INPUT);
pinMode(strobePin, OUTPUT);
pinMode(msgResetPin, OUTPUT);
analogReference(DEFAULT);
Serial.begin(115200);
digitalWrite(msgResetPin, 0); //Initialize the spectrum analyzer
delay(1);
digitalWrite(strobePin, 1);
delay(1);
turnOffLEDs();
}//End setup
void loop() {
displaySpectrum(); //Display the spectrum
}//End loop
//////////////////////////////// FUNCTIONS //////////////////////////////////
-
7/28/2019 A-V LED Cube Final Report
37/42
D a i g l e , H u n t e r , K r e i d e r | 37
//Read the 7-band equalizer
void readSpectrumValues() {
digitalWrite(msgResetPin, 1);
digitalWrite(msgResetPin, 0);
//Band 0 = 63Hz
//Band 1 = 160Hz
//Band 2 = 400Hz
//Band 3 = 1kHz
//Band 4 = 2.5kHz
//Band 5 = 6.25kHz
//Band 6 = 16kHz
for (int band = 0; band < 7; band++) {
digitalWrite(strobePin, 0);
//Read twice, take the average
spectrum[band] = (analogRead(analogPin) + analogRead(analogPin)) / 2;
digitalWrite(strobePin, 1);
}
}//End redSpectrumValues
/////////////////////////////////////////////////////////////////////////////
void displaySpectrum()
{
readSpectrumValues(); //Read in the spectrum values
int scalar = 80;
int adjustmentTimer = 0;
int barHeightA;
int barHeightB;
int barHeightC;
int barHeightD;
int barHeightE;
int maxHeight = 0;
for(int band = 0; band < 7; band++) {
//Will only be using 5 bands//Bands are read in as values from 0 - 1023, scale them down to be 0 - 5
barHeightA = spectrum[0] / scalar;
barHeightB = spectrum[1] / scalar;
barHeightC = spectrum[2] / scalar;
barHeightD = spectrum[4] / scalar;
barHeightE = spectrum[5] / scalar;
if(barHeightA > maxHeight) //Check if this value is the largest so far
maxHeight = barHeightA;
if(barHeightB > maxHeight)
maxHeight = barHeightB;
if(barHeightC > maxHeight)
maxHeight = barHeightC;
if(barHeightD > maxHeight)
maxHeight = barHeightD;if(barHeightE > maxHeight)
maxHeight = barHeightE;
///////////////// FIRST LAYER //////////////////
turnOffLEDs();
if(barHeightA >= 1){
green[20] = 1;
}
-
7/28/2019 A-V LED Cube Final Report
38/42
D a i g l e , H u n t e r , K r e i d e r | 38
if(barHeightB >= 1){
green[21] = 1;
}
if(barHeightC >= 1){
green[22] = 1;
}
if(barHeightD >= 1){
green[23] = 1;
}
if(barHeightE >= 1){
green[24] = 1;
}
convert(green, 'g', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube
digitalWrite(ground[0], 1);
delayMicroseconds(t);
///////////////// SECOND LAYER //////////////////
turnOffLEDs();
if(barHeightA >= 2){
green[20] = 1;
}
if(barHeightB >= 2){
green[21] = 1;
}
if(barHeightC >= 2){
green[22] = 1;
}
if(barHeightD >= 2){
green[23] = 1;
}
if(barHeightE >= 2){
green[24] = 1;
}
convert(green, 'g', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube
digitalWrite(ground[1], 1);
delayMicroseconds(t);
///////////////// THIRD LAYER //////////////////
turnOffLEDs();
if(barHeightA >= 3){
green[20] = 1;
}
if(barHeightB >= 3){
green[21] = 1;
}
if(barHeightC >= 3){green[22] = 1;
}
if(barHeightD >= 3){
green[23] = 1;
}
if(barHeightE >= 3){
green[24] = 1;
}
convert(green, 'g', dataArray); //Convert the binary array into bytes
-
7/28/2019 A-V LED Cube Final Report
39/42
D a i g l e , H u n t e r , K r e i d e r | 39
sendOut(); //Send the frame to the cube
digitalWrite(ground[2], 1);
delayMicroseconds(t);
///////////////// FOURTH LAYER //////////////////
turnOffLEDs();
if(barHeightA >= 4){
green[20] = 1;
}
if(barHeightB >= 4){
green[21] = 1;
}
if(barHeightC >= 4){
green[22] = 1;
}
if(barHeightD >= 4){
green[23] = 1;
}
if(barHeightE >= 4){
green[24] = 1;
}
convert(green, 'g', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube
digitalWrite(ground[3], 1);
delayMicroseconds(t);
///////////////// FIFTH LAYER //////////////////
turnOffLEDs();
if(barHeightA >= 5){
green[20] = 1;
}
if(barHeightB >= 5){
green[21] = 1;
}if(barHeightC >= 5){
green[22] = 1;
}
if(barHeightD >= 5){
green[23] = 1;
}
if(barHeightE >= 5){
green[24] = 1;
}
convert(green, 'g', dataArray); //Convert the binary array into bytes
sendOut(); //Send the frame to the cube
digitalWrite(ground[4], 1);
delayMicroseconds(t);
}
//Stabilization section
//Adjust the scalar if levels are too high/low
//If below 4 happens 20 times, then decrease the divisor
if (maxHeight >= 5) {
scalar++;
adjustmentTimer = 0;
}
else if(maxHeight < 5) {
-
7/28/2019 A-V LED Cube Final Report
40/42
D a i g l e , H u n t e r , K r e i d e r | 40
if(scalar > 65)
if(adjustmentTimer++ > 20) {
scalar--;
adjustmentTimer = 0;
}
}
else {
adjustmentTimer = 0;
}
}//End displaySpectrum
/////////////////////////////////////////////////////////////////////////////
/* This function places the 1x25 binary array into a 1x80
(10 registers x 8 pins = 80 bits) binary array. These 80 binary values
are then converted into a 1x10 byte array of HEX values */
void convert(int tempArray[25], char color, byte byteArray[10]) {
int LSB = 0; //Represents least significant bit of the 8 bits being converted
int MSB = 7; //Represents most significant bit of the 8 bits being converted
int conversionArray[8]; //Array used to store the 8 bits being converted
int byteIndex = 0; //Used to index the byteArray
int indexA = 0;
/* Place the 1x25 binary array into the 1x80 binary array. The location of
the 25 values in the 1x80 array is determined by what color the array
is. First 25 values are reserved for blue, second 25 for green, third
25 for red, and the last 5 values are don't cares. Only one color will
be on at a time. */
//Blue
if(color == 'b') {
for(int i = 0; i < 25; i++) {
eightyArray[i] = tempArray[i];
}
}
//Green
else if(color == 'g') {for(int j = 25; j < 50; j++) {
eightyArray[j] = tempArray[j - 25];
}
}
//Red
else if(color == 'r') {
for(int j = 50; j < 75; j++) {
eightyArray[j] = tempArray[j - 50];
}
} //Red
/* Now convert the 80 bits into 10 bytes and store them in byteArray,
which points to dataArray */
while(MSB < 80) {
indexA = 0;for(int i = LSB; i
-
7/28/2019 A-V LED Cube Final Report
41/42
D a i g l e , H u n t e r , K r e i d e r | 41
}
}//End convert
/////////////////////////////////////////////////////////////////////////////
//This function converts the string of 80 binary values into 10 bytes in HEX
byte binaryToByte(int binary[8]) {
byte sum = 0x00;
//Converts the 8-bit binary number into a HEX byte, which is held by sum
if(binary[0] == 1) {
sum = sum + 0x80;
}
if(binary[1] == 1) {
sum = sum + 0x40;
}
if(binary[2] == 1) {
sum = sum + 0x20;
}
if(binary[3] == 1) {
sum = sum + 0x10;
}
if(binary[4] == 1) {
sum = sum + 0x08;
}
if(binary[5] == 1) {
sum = sum + 0x04;
}
if(binary[6] == 1) {
sum = sum + 0x02;
}
if(binary[7] == 1) {
sum = sum + 0x01;
}
return sum;
}//End binaryToByte
/////////////////////////////////////////////////////////////////////////////
//This function writes the array values to the registers and sends them to the cube
void sendOut() {
digitalWrite(latchPin, 0); //Ground latch pin until done shifting in all data
for(int i = 0; i < 10; i++) {
data = dataArray[i];
shiftOut(dataPin, clockPin, MSBFIRST, data); //Shift in the data one byte at a
time
}
digitalWrite(latchPin, 1); //Send out the data from the registers
}//End sendOut
/////////////////////////////////////////////////////////////////////////////
void turnOffLEDs() {
for(int i = 0; i < 25; i++) {
green[i] = 0;
red[i] = 0;
blue[i] = 0;
}
for(int i = 0; i < 5; i++) {
digitalWrite(ground[i], 0);
-
7/28/2019 A-V LED Cube Final Report
42/42
D a i g l e , H u n t e r , K r e i d e r | 42
}
for(int i = 0; i < 80; i++) {
eightyArray[i] = 0; //Initializes the eightyArray
}
digitalWrite(regResetPin, 0);
digitalWrite(regResetPin, 1);
}//End turnOffLEDs