CSEP567 Lab 6: “Pulse Width Modulation”
Objectives
The goal of this lab is to generate various colors
using a tri-color LED. To select the color to be output we will
create a virtual knob by measuring accelerometer readings through pulse width
measurements. In addition, you will also use pulse width modulation to control
the brightness of the LEDs. In this lab you will learn the following:
-
how to read an accelerometer reading via pulse width measurement ;
-
how to use the input capture on the 16-bit timer on the ATmega16 to do so; and
-
how to adjust the intensity of a light using pulse width modulation.
Important Warnings
Do NOT do either of these two things:
-
The ADXL202EB (the accelerometer evaluation board used in the
lab) is not reverse polarity protected. Do not reverse the +5V and ground
terminals as it will damage the ADXL202EB and make the part unusable.
-
Do not drop the ADXL202EB on a hard surface as it may generate
several thousand g's of acceleration, enough to damage the accelerometer.
Hints
-
Take this lab step by step and incrementally test your code to make sure that
it is working as you expected. Make sure to test pieces of code one at a
time and convince yourself that they are working before moving on to another
piece.
-
The lab is broken up into multiple parts to make the
lab simpler with smaller/simpler tasks that will build to the final
result. It is a good idea to save a copy of your code after each step. If for
some reason you are unable to complete the lab partial credit will be givin for
each completed step.
-
Utilize theLCD and the 7-segment LED displays for debugging.
WARNING: If you update the 7-segment LED displays each time through your main
loop you might not be able to read the numbers because it will be changing the
number on the order of milliseconds.
-
With a small enough period, a human eye should not
be able to perceive any flickering of the LED when the button is not pressed.
If you are seeing flickering it is most likely timing related, such as an
interupt being too long. You should try to eliminate any flicker from your
LED's, however, you should focus on completing the lab first instead of
spending huge amounts of time trying to troubleshoot.
-
Focus on making your system have a reasonable
interface. Do not get stuck trying to get timing calculations to work out
perfectly. The accelerometer is inherently noisy. The important thing is to
create an interface that “feels” right to a human. People will not notice
timing errors on the order of microseconds (maybe not even a few
milliseconds depending on where it is in the code).
-
We are using 2g accelerometers – that means they detect accelerations up to two
times the force of gravity. The parts should not be subjected to too much more
than this – being dropped or banged on a hard surface. Your calculations can
assume that you are only using gravity to determine how far a user has turned
the accelerometer to the left or right. By using this assumption your
calculations will be incorrect because they will not take into account the
force you yourself apply in starting and/or stopping the accelerometer. Treat
this(the starting/stopping acceleration) as noise as it is difficult to account
for this systematically.
Suggested Reading
Resources
Brief
introduction to AVR Programming
avr-gcc manual
Application
notes section for the AVR 8-bit RISC family
Accelerometer(ADXL202)Datasheet
AccelerometerApplication Note on using the Duty Cycle Output
Tri-Color LED Datasheet Note: We will be using Common Anode LEDs.
Color Applets
Suggested Steps
PART 1:
-
Obtain an accelerometer and cable.Wire your accelerometer module into your
breadboard with the cable.
The cable for your accelerometer module uses a black wire for ground, red
for +5 volts, yellow for the Y-axis output, white wire for the X-axis output, and
blue wire for the button (the other end of the button is connected to ground).
Attach the Y-axis output to ICP1 (pin 20) and the
blue wire to the INT1 pin to detect button presses. Remember to add a
pull-up resistor to the button circuit.
Plug the X-axis output into an unused row on your breadboard as we will use it
later in the lab.
-
Refer to page 9 of the accelerometer datasheet to determine
what resistor to add to the accelerometer board at R1. R1 should be
chosen such that the period of the accelerometer’s PWM period
is approximately 4ms. Trim the leads to fit.
-
Review important warnings (YES, AGAIN) and apply power to the
circuit. Observe the y-axis output with an oscilloscope. Measure the period and
min-max duty cycle.
Complete
Worksheet.
PART 2: (Test your code from Part 1 from the prelab)
-
Implement a program that uses timer 1 input capture mode, (accelerometer y-axis
output to ICP1 pin 20), to determine the positive duty cycle of the y-axis
accelerometer. To do this, time the length of the positive pulse of your
accelerometer (rising edge to falling edge) and the length of the period
(rising edge to next rising edge). Use the 7-segment LED to display a "1" when
the accelerometer has a duty cycle less than 50% and a "2" when the
accelerometer has a duty cycle greater than or equal to 50%.
NOTES:
-
You should choose as small a prescaler factor as possible for Timer 1 to
increase the accuracy.
-
Assume a period of 4 ms. for the Accelerometer outputs.
-
Use TCNT1 and ICR1 to access 16-bit values instead of using the 8-bit registers
(i.e. ICRL & ICRH and TCNT1L & TCNT1H)
-
Remember to set TCNT1=0 when you want the counter restart at 0. The input
capture interrupt does not reset TCNT1 to zero automatically
PART 3: (Test your code from Part 2 from the prelab)
-
New program: Define the x-axis of the accelerometer as an input on INT0 (pin
16).
-
Use INT0 and Timer2 to create a manual interupt capture routine to determine
the positive duty cycle of the x-axis.
-
Implement a program that measures the x-axis and drives the 7-segment LED as in
part 2.
PART 4: (Integrate Parts 2 & 3 and HSV)
GOAL: To generate various colors on the tri-color LED using the accelerometer to
select color and the potentiometer to adjust brightness. A user should be
able to press the button and move the accelerometer until they find a color
they want. On button release the H & S value should lock in. A user should
be able to update the brightness of the color they choose by adjusting the
potentiometer at any time.
-
Use the provided HSV to RGB code to control the tri-color LED.
Code
H->x-axis
S->y-axis
V->ADC value of potentiometer (this controls brightness)
-
To eliminate gitters make sure to average your values (H, S, & V).
-
The color should only change while the user holds the button on the
accelerometer down. Brightness should update anytime the value of the
potentiometer is changed.
-
Suggested timer uses:
-
Timer0 -> used to generate the 3 PWM’s needed for the tri-color LED
-
Timer1 -> input capture for the y-axis (possible button polling)
-
Timer2 -> used with INT0 to perform input capture for the x-axis
Deliverables
For all files turned in, the comments at the top of the file should contain:
-
Both partners' full names.
-
The lab number and the part of the lab (e.g. “Lab 6”).
-
Demonstrate part 4 to a TA. You can either do this during this lab, or
during the first 1/2 hour of the next lab.
-
You will not receive full points if there is noticible flicker on any of your
LED's when the button on the acclerometer is not
pressed.
-
The light levels of the LED's should not change until the button is pressed or
your potentiometer is adjusted (which should only adjust the brightness).
-
It should be possible to display all major colors on your Tri-Color LED (The
more distinct colors the better!).
-
Turn in hardcopy of your commented C code.
-
Make sure that the code in your interrupt handler is as minimal as possible. It
is fine to update state or do a little bit of work in the interrupt handler. We
will grade on how you designed your program to minimize code in the interrupt
handler.