Design
Electrical Design
The electrical components used are:
Figure 2. Onboard ATmega644 microcontroller.
-
On-board ATmega644 microcontroller (on development board)
-
Stationary ATmega644 microcontroller (on development board)
-
5 MAX 6966 controller chips
-
14 RGB LEDs
-
1 9V battery
-
1 pair of IR transmitter and receiver
-
2 WI.232FHSS-25-R radio transceivers from Radiotronix
-
2 WI.232FHSS-25-FCC-R break out boards from Radiotronix
-
LP2951 Linear Regulator
-
LM340-15 Linear Regulator
-
Various Resistors and capacitors
-
Various wires and header pins
There are two main electrical designs to this project, the onboard
(attached to spinning arm) system and the stationary system. The primary
purpose of the onboard is to actually turn on and off the LED's based
on a two dimensional matrix (further described in the software section).
The onboard circuit consists of an ATmega644 (
Figure 2)
microcontroller which is powered by a 9V battery (also onboard). In
order to turn on the LEDs, the microcontroller will act as an SPI master
and the MAX 6966 will act as SPI slaves. The master, the
microcontroller, will communicate to the slave chips via the SPI bus. It
will send serial commands to write the registers on the MAX6966 chips.
On the slave end, the target MAX 6966 chip will receive an 4-bit value
that it will correspond to a PWM duty cycle outputting on specific port
connected to a target LED. The onboard circuit schematic shows all five
MAX 6966 chips controlling 14 RGB (red, blue, and green) LED's. The max
chips are powered by a 3V3 regulator from the 5V rail from the
microcontroller and the LED's will be powered from that rail as well.
Also, the onboard microcontroller will be calculating the RPM (Rotations
per Minute) at every rotation to adjust the display depending on how
fast the arm is spinning. Lastly, the onboard microcontroller will
communicate with the stationary microcontroller via radio units.
Figure 3. Onboard MAX 6966 chips that control the LEDs.
Each MAX6966 chip (
Figure 3) has 10 output pins and an SPI
input bus. Since each LED is controlled by 3 pins, each MAX6966 chip can
control 3 LED's. The SPI control bus comes from the microcontroller
(master) and chooses which MAX 6966 chip (slave) to talk with and
control pin outputs. Each pin on the MAX6966 chip can be chosen to turn
on or off a color for a specific LED. Since we have 14 LED's (needing 42
driver pins), we decided to use 5 MAX6966 chips (corresponding to 50
outputs), each with its own chip select.
To collect the RPM data needed for our timing calculations, we have
the microcontroller connected to an infrared (IR) circuit board. This
circuit consists of an IR transmitter and receiver which face downwards.
Each time the circuit board passes by the white piece of paper, it will
send a signal to the microcontroller to trigger an interrupt to
calculate the rotation period.
The wireless transceivers used to send images are connected to their
respective microcontroller boards using the UART TX and RX pins. The RX
and TX pins on the wireless transceiver are connected to their
counterparts TX and RX, respectively, on the microcontroller.
Figure 4. Stationary transmitter connected to computer.
All of the power needed by the electrical components (not including
the microcontroller) is from the VCC from the microcontroller. In order
to allow the microcontroller to provide enough current to power all 14
LEDs, 5 MAX 6966 chips, IR circuit, and wireless transceiver, we have a
high current (1A) LM340-15 linear regulator on the microcontroller to
limit the 9V from the battery to 5V. Furthermore, since the MAX 6966
chips take 3.3V, we have an LP2951 linear regulator to limit the 5V VCC
output from the microcontroller to 3.3V.
The primary function of the stationary circuit is to act as the user
interface so that the user can upload whatever image to be displayed (
Figure 4).
Another function of the stationary circuit is to select different
functions for the onboard board to perform such as animations, clearing
the display, etc.
Since our motor is an AC motor that spins at 1,600 RPM as soon as it
is plugged into the wall socket, this is too fast for our application.
Thus, to reduce the speed and to prevent the motor from going from 0 to
1,600 RPM instantly, we are using a variable AC adapter. It is actually a
light dimmer from
Lutron Electronics, but it is essentially a
variable AC, and it has a dial for choosing how much amplitude we want
to give to the motor. This allowed us to perform safer tests, without
worrying about pieces flying off of the spinning arm.
Hardware Design
-
Bodine Electric Company AC motor
-
Base support plate
-
Vertical support plate
-
Plexiglas support arm
-
Plastic arm (for LED)
-
Several 3M dual locks
-
Electrical tape
-
Hot glue
-
Various size screws
The main components of our hardware design is an AC motor, a mounting
bracket for the motor, and the spinning arm which is comprised of a
Plexiglas piece and a plastic piece. The Plexiglas acts as the main
support for the arm and is connected to the spinning shaft of the motor,
while the plastic piece has for the 90 degree bend at one end to
provide a platform for mounting the LED's.
Our AC motor does not have any self-supporting component to stand
upright. Thus, we have built a mounting bracket that will hold to make
sure the motor is standing upright. The bracket consists of the base
piece and the vertical support piece. Both pieces are approximately � of
an inch thick. The vertical support piece is connected to the base
piece at a 90 degree angle with two size 8-32 screws. Next, the motor is
attached to the vertical support piece with four size 10-32 screws in a
square orientation. The four tapped screw sockets on the motor was
initially already there, so we had to just drill four holes in the
vertical support that are lined up with the provided sockets on the
motor. This mounting bracket provides great stability while the motor is
spinning at high rates. Load balancing of the spinning cantilever is
the main reason for the stability during spinning. As an addition
precaution , the user should clamped the bracket to a table during the
spinning.
Figure 5. Spinning arm attatched to rotor.
For the spinning arm, a piece of Plexiglas 1/4 of an inch wide and
1/2 foot long is attached to the spinning shaft of the motor. This shaft
is approximately a size N hole with a small flat edge. In order to
secure the Plexiglas firmly to the shaft without it sliding along the
shaft in any way, we drilled a hole size that is just a bit smaller than
size N (to make it a very tight fit), and drilled a small hole on the
side to insert a set screw that will push against the flat edge. We
decided to use Plexiglas because it is a strong yet light material.
Lastly, a thin plastic piece was bent at 90 degrees near one end and
attached to the Plexiglas. We are using this plastic piece mostly
because it is easily bendable while also light.
In order to make sure we don't get too much wobbling when spinning at
high rates, we positioned the electrical components on the spinning arm
to provide good counterbalance on both sides (
Figure 5).
Software Design
The software design of this project is relatively simple. We are
running three tasks; task1 to record and calculate the current RPM at
every revolution, task2 to write the appropriate data (based on matrix)
to the respective MAX6966 chip port via SPI, and task3 to run the
animations. The frequency of task2 being executed depends on the
measured RPM values by setting the release and deadline to the amount of
time per "segment" (each column in our matrix). Each "pixel" of the
image is represented by one element in the matrix. Currently, we have a
14x90 matrix displaying only on half of a circle, but it is possible to
expand the resolution in the future. Furthermore, each element in the
matrix is a 16 bit number where the first 4 bits are for the red value,
the next 4 are for the green value, and the last 4 bits are for the blue
value of an LED. These 4 bit values are mapped to 8 bit values to
actually set the intensity level of the LED's. The main difficulty of
the software was to setup the SPI communication between the
microcontroller and the MAX6966 chips.
The MAX6966 has 10 I/O ports, each capable of outputting an 8-bit PWM
signal. Each port is controlled by registers onboard the chip. The SPI
bus is used to communicate with the MAX6966 and set both the explicit
registers which control the ports and the implicit registers which
control the state of the chip (power up sequences, shutdown mode, run
modes, etc). The MAX6966 is a current sync which means to turn on an
LED, we short the Port pin to ground completing the circuit and turning
on the common anode RGB LED. To program the chip, we send commands to
the register to allow maximum current draw through each pin (20ma) and
set every port high (LED's are wired low logic). We put the chip in run
mode and then we are ready to set the outputs of every pin and control
three RGB LED's (per MAX6966 chip).
In order to display anything, a transmitter must send pixels to the
onboard receiver which will then populate the display matrix in the
microcontroller with the sent pixels. Thus, there are two components:
the transmitter code and the receiver code. The transmitter code is very
straightforward; we transmit each pixel at a time as a packet. Before
we send each packet, we must send a SYNC byte and then an ADDR byte. The
SYNC byte will sync the transmitter and the receiver, and the ADDR byte
will let the receiver receive data only from a transmitter with that
expected ADDR byte. After these 2 bytes are sent, we send the column and
row byte. Next, we break the 16 bit data into 3 bytes that contain the
first 3 nibbles of the 16 bit data and send them across. Lastly, we send
an antisync byte to let the receiver know that it has finished sending
data.
The code for the receiver is a bit more complicated. It involves a
state machine with states WAIT_SYNC, WAIT_ADDR, and WAIT_DATA. State
WAIT_SYNC waits for the SYNC byte from the transmitter and once it sees
that, it goes to the WAIT_ADDR state. State WAIT_ADDR waits for the ADDR
byte and when it sees it, it goes to the WAIT_DATA state. Otherwise, it
goes back to WAIT_SYNC state. In WAIT_DATA state, the processor waits
to get data for the column and row byte and then the data bytes. After
all the data bytes and the antisync byte are received, the state machine
will proceed to recompile the individual bytes back to a 16 bit data
and put it in the matrix element at the received row and column.
We have also added animations to our project. This specific animation
was hardcoded to move the 'S' in "SEXY" back and forth repeatedly. We
did this by turning off the LED's in the previous location of 'S' and
then turn on the LED's in the next location of 'S'. As of now, our
animation code remains to be hardcoded and a possible extension for this
project can be a more user-interactive animation.
Testing
Hardware Testing
The structural components of the design were very straightforward; we
needed a design that would allow the motor to stand upright instead of
lying down. Thus, we eventually came up with the L shaped mounting
structure. The actually machining process for this piece took time since
neither my partner nor I have had much machining practice. However, it
was just a matter of drilling two holes through the vertical plate which
lined up with the two holes in the base plate. The important step was
to tap the base plate, but use a body drill for the vertical plate for
the same hole size. This allows the screw to push the vertical plate
against the base plate tightly. Our original efforts had both holes in
the vertical and base plate tapped, causing the joint to be very weakly
attached. After the holes on the vertical plate were drilled with the
body drill, the joint became very strong.
After attaching the spinning arm (the last structural component), we
tested spinning the motor. The first test proved that it was necessary
to clamp the mount to the table while spinning. This was because since
the motor was just an AC motor with the power outlet as the power
source, the motor settings were either off or on at maximum speed. Even
with the mount clamped down, when the motor was turned on, the motor
would shake the entire bench. This was clearly too dangerous to actually
test with any electrical devices attached to the arm. To allow a
variable speed for the motor, we used a light dimmer that is basically
just a variable AC controller. This allows us to adjust the speed of the
motor progressively, allowing us to test with much lower RPM's.
Next, the electrical components were added to the arm. The electrical
components that we used in our initial light test consisted of a 9V
battery, the target board, the IR sensor, a through-hole board with one
MAX6966 chip, and another through-hole board with three LED's. Aside
from the target board, all the other components were attached on one end
of the arm. This was the only viable option because the spinning arm
was connected to the shaft at just one end of the arm, so there was no
space to add counterweights. Thus, when we started spinning at a slow
200 RPM's, the system became very unstable and started to shake the
table. At this slow speed, however, it was enough to show a proof of
concept because we can still discern the image. Once this was done
successfully, we began to expand our design to include 14 LED's and to
improve load balancing.
With the 14 LED design, we were also able to move the bottom
Plexiglas piece more to the other side to allow space to put the
microcontroller and the battery. This design allows us to spin the arm
at near maximum speed of the motor without any signs of structural
instability. The only main issue that we had left was to figure out the
wiring of all the electrical components. Since we were using 14 LED's,
that means we needed five MAX 6966 chips, mounted on two through-hole
boards. Once everything was connected, insulated, and tested, it was
turn to test the software.
Software Testing
The first piece of code that was written and tested was the SPI code.
Once this was tested and working successfully, we were able to write
the code based on TRT operating system.
Next, we added the code to measure the RPM of the system. Amazingly,
our code worked without any major bugs with the three LED's. Our biggest
concern was that TRT could possibly jump to another task while in the
middle of writing SPI to one of the chips. However, this proved to not
be a problem after testing. One issue that was not considered at this
point was displaying all three colors for each LED. For the sake of
quick testing, our matrix consisted only of either on or off for each
LED, where on is just max intensity in red color. Our next expansion
design includes the use of all the colors for each pixel.
A major problem in the updated code for 14 LED's was a problem with
having enough memory. Creating an uint32_t matrix with size 14 by 180
causes us to use four times the amount of memory that we have. Thus, we
proceeded to reducing the number of column pixels to 90 while keeping
the resolution the same. This just meant cutting our display to just
half the circle instead of the entire circle. Also, instead of using
uint32_t, which is 32 bits, we used uint16_t and use 4 bits for
intensity for each LED color. These 4 bits will then be logarithmic
scaled to an 8 bit number.
Another major problem we encountered was intermittent receiver
failure. However, resetting power on both the receiver and the
transmitter would fix the problem. Other bugs such as turning off the
transmitter while it's in the middle of sending data to the receiver
would also cause the receiver to freeze (the LED's still displayed the
image right before it froze since the MAX chips control the LED's, thus,
hard to debug). We were able to narrow the problem down to our
receiver's state machine, since it had several holes that could cause
the onboard microcontroller to freeze. For example, turning off the
transmitter in the middle of transmitting could leave the receiver stuck
in the WAIT_DATA state since it never got the antisync byte. Another
problem was that we did not check to see if row and col were within our
useable limits. Thus, if we were to receive mixed up data and set col to
a number greater than 89, then our code would crash because it would
try to access an index that's out of bounds (we have 90 columns).