CSE466 Lab 3: “Pulse Width Modulation and Electric Field Sensing”
Objectives
The goal of this lab is to control the color of a tri-color LED pulse-width
modulation. You will control the color of the LED with an
accelerometer and with an electric field sensor that you will construct.
You will learn the following concepts:
-
how to use PWM to control the brightness of an LED
-
how to use input capture to determine the duty cycle of a PWM input
-
how to implement an electric field sensor
Hints
-
Take this lab step by step and incrementally test your code to make sure
that it is working as you expected. Coding the entire project first then
trying to debug a problem can be challenging without the usual forms of
debugging. 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 given
for each completed step.
-
Utilize 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. If you are seeing
flickering it is most likely timing related, such as an interrupt being
to long. You should try to eliminate any flicker from your LEDs.
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
electric field sensor and accelerometer are both somewhat 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).
-
DON’T USE FLOATING POINT NUMBERS. The ATmega16 does not
support them.
Suggested Reading
Resources
Suggested Steps
PART 1:
-
Read all of the directions for Part 1 before doing ANYTHING. Often
the next step reveals why the current one is important.
-
Remove the 7-segment display from PORTD.
-
Disconnect the decimal point form the 7-segment display on PORTB to free
up a pin for later use. (The remainder of this lab assumes that this
is PB0).
-
Remove the photoresistor from the board and move the potentiometer to pin
PA1.
-
Add the tri-color LED to your breadboard by connecting the Common Anode to
Vcc, the red LED to pin 21 (use
a 560Ω current-limiting resistor), the blue LED to pin 19
(use a 300Ω current limiting resistor), and the green LED to pin 18
(use a 300Ω current-limiting resistor). NOTE: To aid in debugging you may
want to add 3 separate LEDs in parallel to your
tri-color LED to see the light level of each color segment; however, make
sure the parallel LED is separate (i.e. has its own current limiting
resistor).
-
A cable has been provided for your accelerometer module, using black wire
for ground, red for +5v, yellow wire 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).
-
Wire your accelerometer module into your breadboard. Attach the Y-axis
output to ICP1 (pin 20).
-
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 the accelerometer worksheet.
PART 2:
-
Read all of the directions for Part 2 before doing ANYTHING. Often
the next step reveals why the current one is important.
-
Download the PWM sample code. It uses the output
compare capability of timer 2 to generate a PWM signal to control the
brightness of an LED connected to OC2 (pin 21). Modify the PWM sample so
that you can control the LED brightness by adjusting the value of a
potentiometer.
-
Implement a program that uses timer 1 input capture mode to determine the
positive duty cycle. 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 50%.
NOTES:
-
You should choose as small a prescaler factor as possible for Timer 1 to
increase the accuracy.
-
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 to restart at 0. The
input capture interrupt does not reset TCNT1 to zero automatically.
-
Combine step 1 and 2 so that when you turn the accelerometer to the
right it makes the LED brighter and when you turn it to the left it makes
the LED dimmer. NOTE: If you turn the accelerometer-based virtual switch
past 90 degrees it will start to decrease again. Use the one 7-segment LED
display to output the most significant byte of your light level (the value
of OCR2) in hex.
PART 3:
-
Read all of the directions for Part 3 before doing ANYTHING. Often
the next step reveals why the current one is important.
-
You will need to manually generate three separate PWM signals to drive the
tri-color LED. Use timer0 to generate 3 separate PWM signals for
each segment. A period of <15ms should not be visible to a human. (For
the end of the lab we encourage using a period less than 15 ms, but start
at 15 ms and then reduce it as a smaller period will be more taxing on the
processor.)
-
Use the potentiometer and the ATMega16's ADC to test your manual PWM
signal. Use the ADC readings (0-255) to control the
LEDs brightness. You might want to avoid
using free-running mode to trigger the ADC as it will cause timing
problems later. A good auto-trigger is Timer0 output compare (same
interrupt that should be generating your PWM).
PART 4:
-
Read all of the directions for Part 4 before doing ANYTHING. Often
the next step reveals why the current one is important.
-
Before doing any wiring for this part, make sure you have a program on the
microcontroller in which pin PA0 is configured as an input in your
program, PB0 is an output, and that PB0 is set to output low. This
will ensure that when you apply power to the board, the microcontroller is
not trying to drive the output of the amplifier.
-
Refer to
this
schematic, which shows what you will need to add to make the field
sensor work. Note that it does not show components like the
7-segment display which should already be on your breadboard.
-
Obtain a TLC084 quad op-amp IC and 27 pF capacitor from the TAs. The
resistors you will need to add to your circuit can be found in the supply
cabinet.
-
Add the TLC084 quad op-amp IC to an empty space on your breadboard near
PORTA on the ATmega16. Wire the chip to implement the amplifier
circuit in the schematic, and connect the output of the amplifier to PA0
(pin 40.) Move the potentiometer to PA1. You may remove the
photoresistor. Try to keep your wiring especially neat for this
section, since long wires could act as antennas.
-
Connect the transmit antenna to pin 1. You will need to disconnect
the decimal point on the 7-segment display to free up a pin on PORTB.
-
Connect the receive antenna to the input to the amplifier circuit.
Try to route your receive and transmit wires so they are not close to each
other.
-
Apply power to the board. Use a multimeter to measure the voltage
between digital ground (the negative side of the power supply) and the
analog ground (AGND on the schematic.) You should see approximately
2.5 volts at this point. Measure the voltages at the input and
output of the amplifier circuit. These should also be about 2.5V
-
Connect an oscilloscope probe to pin PA0. (Make sure you connect the
oscilloscope ground to the digital ground, not AGND.) You
should see an approximately flat line at about 2.5 V. Now, touch the
receive antenna. You should see a lot of noise on the oscilloscope.
-
If you did not get the results from steps 7 and 8, something is
wrong. Check your circuit and wiring. Do not proceed until
your circuit passes these checks.
PART 5:
In this part, you will write code to utilize the sensor you just wired.
Read the following information, which describes the theory behind the
sensor. Then, complete the steps outlined in the implementation section.
IDEA:
The transmit and receive electrode are the plates of a capacitor.
Putting your hand in the vicinity of the capacitor plates changes the value of
the capacitance. So hand proximity will be inferred from capacitance
changes. We will be measuring small changes in capacitance, so we will
need sensitive measurement techniques. There is substantial noise (1/f
or “flicker” noise, as well as 60Hz noise, etc) at low frequencies, so we will
be modulating up to higher frequencies. (Later we will also see that
modulation can allow us to measure more than one channel
simultaneously.) Thus, we will measure the capacitance between the TX
and RCV electrodes by looking at its response to an AC signal.
When we apply an AC voltage V=A cos(2 pi f t) to a capacitance C, a current I
= C dV/dt is induced. dV/dt = -2 pi f A sin(2 pi f t), so I = - C 2 pi f
A sin (2 pi f t). We will use the microcontroller to generate a square
wave (instead of a sine wave) carrier. The variable capacitance caused
by hand motion amplitude modulates this carrier. After some basic signal
conditioning electronics on the receive side, the microcontroller will
demodulate the received signal in software to recover a value proportional to
C.
DESCRIPTION of SCHEMATIC:
The microcontroller will generate a square wave voltage on PORTB which is
directly applied to the TX electrode. This induces a current on the
receive electrode that is proportional to the derivative of the transmitted
voltage (and to the capacitance between TX and RCV, which we are trying to
measure). We are interested in the amplitude of the received signal,
which is affected by hand position. The derivative of a square wave is a
train of positive- and negative-going spikes. The first op-amp gain
stage (U2A, one of 4 op-amps in the TLC084 package) is current amp (no input
resistor, large gain 1M resistor in its feedback network) and also does some
integration (the 27pF capacitor in the feedback network) to un-do the
derivative and approximately restore the square wave. The second gain
stage (U2D) is a classic inverting (voltage) amplifier with a gain of 10
(100K/10K). It simply amplifies the voltage output from the first stage.
The only remaining portion of the schematic provides the “analog
ground.” The voltage divider formed by R4 and R5 provides 2.5V that the
single supply op-amps will use as “bias.” The op-amps only have +5V and
GND power supply connections (no negative voltage rail, like some
op-amps). So, a voltage signal of -2.5V will be represented by 0V; a
voltage signal of 0V will be represented by 2.5V; and a voltage signal of
+2.5V will be represented by +5V.
CODING:
Here is pseudo code for what you need to implement
// Set PORTB as output
// Set ADC0 as input; configure ADC
NSAMPS = 200; // Try different values of NSAMPS. Look at the SNR /
update rate trade off
Acc = 0; // acc should be a 16 bit variable
For (i=0; i<NSAMPS; i++) {
SET PORTB
HIGH
Acc = Acc +
ADCVALUE
SET PORTB
LOW
Acc = Acc -
ADCVALUE
}
Return Acc
IMPLEMENTATION:
-
Write a program that implements the pseudocode given above.
-
There are a number of tools that will be useful in debugging your circuit
and program.
-
The 7-segment display can be used to display a hex number, though if you
update it too frequently, it may change too fast for you to read.
Displaying the highest 4 bits of a variable may be most useful.
-
The JTAG debugger lets you view the values of registers and variables
while your program is paused. Set a breakpoint to occur after the
sensor completes a measurement so that you can view the result of the
measurement.
-
The oscilloscope will allow you to look at the analog signals being
transmitted and received.
PART 6:
-
Read all of the directions for Part 6 before doing ANYTHING. Often
the next step reveals why the current one is important.
-
Combine the electric field sensor, potentiometer, and one axis of the
accelerometer to each control one segment of the RGB LED.
-
The accelerometer should control the red channel, the potentiometer should
control the green, and the field sensor should control the blue. To
verify that each sensor is working independently, it may help to have
separate LEDs wired in parallel with the 3 colors in the RGB LED.
(See part 1.5.)
-
The electric field sensor will produce a wide range of values, which will
depend on other objects that are nearby your breadboard. You will
need to use the JTAG debugger to determine this range of values each time
you set up your board, and adjust constants in your code to scale these
values to a range that is useful for controlling the PWM of the LED.
-
Timing is critical for the electric field sensor. If an interrupt
for something else happens during a reading from the sensor, it may affect
the measurement. Try to schedule events so that you read from the
sensor during the time in between PWM interrupts. Also, do not try
to read from the field sensor and the potentiometer at the same time since
there is only one ADC.
Extra Credit:
-
Implement a method of calibrating your sensor that removes the need to
manually adjust constants in your code each time you set up the sensor.
-
Your method of doing this is up to you, but it should be intuitive and
easy to use. You may add another pushbutton to trigger calibration
if you want.
-
After your calibration procedure has been performed, one should be able to
adjust the LED brightness through its full range by moving a hand above
the sensor.
Question 1: Describe why the code in your interrupt handlers could not be
located in the main body of the program. Basically explain your design and
why it was important for the specific code to be in an ISR.
Question 2: Explain why it is necessary to adjust the sensor each time it
is moved to a new location or environment.
Question 3: Outline the timing of events in your program. When do your
various interrupts occur in relation to each other? What timing decisions did you
make to maximize the accuracy of the e-field sensor?
Question 4: Based on the lecture slides, briefly explain how the op-amp works.
(i.e: how it works? what does it do? why do we need the op amp?)
Deliverables
Submit the files through Catalyst Tools at:
·
AA
section
·
AB
section
For all files turned in, the comments at the top of the file should contain:
-
Both partners' full name, login and student number.
-
The lab number and the part of the lab (e.g. “Lab 3”).
-
Demonstrate part 6 to a TA. You can either do this during this lab, or
during the first 1/2 hour of the next lab.
-
Turn in soft copy 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.