CSE 466 Lab 3: Pulse Width Modulation and Electric Field Sensing
In the first section of this lab, you will learn two methods for generating pulse width modulated signals with the ATmega16, which you will use to vary the intensity of the red, green, and blue LEDs in an RGB LED. You'll implement a simple colorspace conversion on your microcontroller to allow the hue of the LED to be changed with a potentiometer.
In the second section of this lab, you will learn how a general-purpose microcontroller can be used to implement a new type of sensor from scratch. You will build a one-dimensional electric field sensor that will be able to sense the distance to your hand or other grounded objects.
Suggested Reading and Resources
- As usual, read all of the directions before proceeding. Often, the next part of the lab reveals why something is important.
- Keep your interrupt handlers short. For the second part of this lab, it really matters!
- Practice incremental design and debugging strategies. You're going to be working with programs that require careful timing and have limited resources available to debug. Even the JTAGICE is only so helpful; it's hard to test timing when you're stepping through your program. Test things as you work on them and verify that each part works as you add it.
- When you are working with the RGB LED, sometimes it's hard to tell what segments are on because the colors mix together. You might find it helpful to wire three regular LEDs in parallel with the three segments in the RGB LED for debugging. Note that these will need their own current-limiting resistors.
Part 1: Pulse-Width Modulation and Color Space Conversion
- Remove the 7-segment LED on PORTD.
- Add the RGB LED to your breadboard. Connect the common anode to Vcc, the red segment to pin 21 via a 560Ω current-limiting resistor, the blue segment to pin 19 via a 300Ω current-limiting resistor, and the green LED to pin 18 via a 300Ω current-limiting resistor. It is okay to substitute the resistors for nearby values if the exact ones are not available, but err on the side of less current through the LED instead of more.
- Download the PWM sample code. It uses the output compare capability of Timer 2 to generate a PWM signal on pin OC2 (21). Run it on your ATmega16 and verify that the red LED changes brightness.
- Modify the sample code so that you can adjust the brightness of the red segment of the RGB LED using your potentiometer.
- Implement pulse-width modulation control for the green and the blue segments of the LED as well, using the output compare functionality of Timer 1, configured as an 8-bit timer. Set up your program so that you can press a button on your breadboard to switch between adjusting the red, green, or blue component of your LED. Remember to debounce your button.
- Now, modify your code so that the brightness and saturation of the LED are held at 100%, and the potentiometer adjusts the hue. Figure 1 shows the relationship between the hue and the red, green, and blue values. For this part of the lab, you may hold saturation and brightness (value) fixed at 100%.
- The ATmega16 does not have floating point hardware. Do not use floating point arithmetic in your code.
- The ATmega16 has a hardware multiply unit, but no divider. Division by powers of two is fast, since it can be implemented as a bitwise shift to the right. Division by other values will be done iteratively and takes more time. Keep this in mind when writing your colorspace conversion code.
|Figure 1. Relationship between hue angle and RGB values with saturation and value at 100% (source: Wikipedia)
Imagine that you were using a processor that did not have three output compare pins available to generate the three PWM signals for the LED, but you do have a timer interrupt available. Write an interrupt service routine that implements pulse-width modulation for three LED channels in software.
You may find it helpful to actually try implementing this exercise on your ATmega16.
- How many bits of resolution for setting the duty cycle does your solution allow?
- In order to minimize flicker of the LED, you should keep the period of your PWM under 15ms. How often must your timer interrupt occur to meet this condition?
- Why might you choose to use fewer bits of PWM resolution?
Part 2: Building an Electric Field Sensor
In this part of the lab, and continued next week, you will build a simple electric field sensor. Your completed circuit will detect the distance between your hand (or another object with high capacitance to ground) and the board. You will send the reading from the sensor to the PC over USB, which will allow you to vary the hue, saturation, and value of a color by moving your hand over the board. This color will be sent back to your circuit, which will display it on the RGB LED.
Since making the electric field sensor work properly takes a bit of planning and calculation, this week you will do the planning and setup, and next week you will write most of the code for the implementation.
Theory of Operation
Our simple electric field sensor is simply a board with two electrodes in the form of large square copper regions. One of these electrodes will be the transmitter and the other will be the receiver.
We will use a timer and interrupt on the ATmega16 to generate a square wave at the transmit frequency. This square wave will go between 0V and 5V with a duty cycle of 50%. We will then feed this signal into a resonant LC circuit. If the square wave is at the resonant frequency of the resonator, then the output will be a high amplitude (on the order of tens of volts to a hundred volts) sine wave, which we will connect to the transmit electrode. The changing electric potential on the electrode will create an AC electric field.
The electric field emitted from the transmit electrode will pass through the receive electrode, which will cause a small AC current to be induced. We'll use two op-amps to modify this signal before feeding it into the ADC on our ATmega16. The first stage will convert the current flowing into the electrode to a voltage, and the second is a voltage-gain stage that will amplify the voltage to a range appropriate for the ADC.
We will then use the ADC to sample certain points on the received waveform, which will allow us to determine the phase and magnitude of the received signal.
When a grounded object, such as your hand, comes in range of the electric field sensor, some of the current from the transmitter is shunted to ground and less will go into the receive electrode. As a result, the magnitude of the received signal will be smaller.
There are two components required to implement the sensor on the ATmega16. To operate the transmitter and generate an alternating electric field, the microcontroller must generate a square wave at the desired transmit frequency. We'll do this with Timer 0's output compare interrupt. The associated ISR will be very simple: it just has to toggle a pin on and off. By selecting the prescaler and output compare values, we can precisely set the frequency of the square wave.
- Write code to set up Timer 0. Start with a prescaler value of 1:1 and an output compare value of 255. Use CTC mode for the timer so that it resets when the output compare value matches.
- Write the ISR for Timer 0's output compare interrupt. This ISR should be very, very short (1 line!) This ISR should toggle the state of pin 22 each time it runs.
Question 2: Write an equation to determine the frequency of the transmitter output waveform fT for a given prescaler value pT0 and output compare value c. Remember that an output compare value of 63, for example, takes 64 timer counts to match (the timer starts at 0). The exact frequency of the crystal you are using is 7,372,800 Hz—do not use an approximation.
We will use the ADC in free-running mode to sample the received waveform. We want to take ADC samples at points corresponding to 0˚, 90˚, 180˚, and 270˚ on the waveform. In order to make this happen, the prescaler for the ADC and the prescaler and compare value for timer 0 need to be carefully chosen so that an ADC sample occurs some integer number of periods of the transmit waveform after the previous, plus one-quarter period (90˚).
- Read the ATmega16 datasheet's section on the timing of the ADC module. Note how the ADC clock is derived from the system clock, and how many cycles of the ADC clock pass between samples.
Question 3: Write an equation to determine the sample rate of the ADC, fS, for a given ADC prescaler value pADC.
Now, we need to determine the frequency at which we're going to transmit, and the prescaler and output compare values that are necessary to set everything up. Ideally to be robust to noise we want to keep the transmit frequency as high as possible, within the constraints of our microcontroller. One important constraint is that the successive approximation ADC in our ATmega168 can't really provide useful values if its clock is running faster than 1 MHz. Another important consideration is the time it takes to handle the ISR for generating the square wave, which happens twice per period of the transmit waveform, and the time it takes to read and accumulate the value from the ADC, which happens once per ADC sample.
Question 4: Using your two equations and the above constraints, determine values for pADC, pT0, and c that satisfy the condition:
with n being a small integer. This relationship should be exact; an approximation won't work here!
Consult with a TA to verify that you have chosen reasonable values before proceeding.
Building the Sensor Hardware
Since the transmit circuitry is sensitive to capacitance, and the receive circuitry is somewhat sensitive to layout considerations, we've prepared a printed circuit board specifically for this lab. The PCB also contains the transmit and receive electrodes.
Refer to the schematic while assembling the board.
|Figure 2. Completed E-Field Sensor Board
- Obtain a blank PCB from a TA, in addition to the following parts that you will need to assemble it:
- A MCP6024 or TL084 op-amp (you may already have one of these in your kit)
- a 1x2 pin header and a 1x3 pin header
- a 14-pin DIP IC socket (optional, but makes life easier if something should happen to your op-amp and it needs replacement)
- a 10 mH inductor
- Resistors and capacitors from the supply cabinet (consult the schematic for values.)
- The capacitors in the transmit resonator do not have specified values on the schematic, since the values are different for different frequencies. Compute the total amount of capacitance you will need for the transmit frequency you have chosen. The resonant frequency of an LC circuit is given by the following equation:
There are five capacitor positions, C3 through C7, which are wired in parallel to allow you to combine capacitor values to add up to the value you need.
Question 5: Show your computation of the required capacitor value in your lab write-up.
- Solder the components onto the PCB. If you have never soldered before, consult with someone who has or a TA. There are also many excellent soldering tutorials available on the internet (see the suggested reading section). It is recommended that you solder the resistors first, then the IC or IC socket, then the capacitors, inductor, and pin headers. (Shortest to tallest components.) This way, when you turn the board over to solder the bottom, the board resting on the table will hold the component you are working on against the board.
- Note that you should solder the pin headers so that the long pins face downward, so that they can be used to plug the board into your breadboard.
- Make sure you solder the IC or IC socket on in the proper orientation. The notch in the rectangular outline on the board silkscreen indicates the notched end of the chip/socket.
- Do not solder pin headers to TxAnt and RxAnt.
Testing the Hardware
- Verify that there are no shorts between Vcc and GND, between Vcc and AGND, or between GND and AGND.
- Plug the sensor board into your breadboard so that the electrodes overhang the edge of the board. (We don't want the capacitance of the breadboard underneath the electrodes.) Wire Vcc and GND, connect RxOut to ADC input 0, and TxIn to the pin that generates your square wave.
- Verify that the voltage of AGND is approximately halfway between Vcc and GND.
- Adjust the constants in your code to the values you calculated in Question 4, and load your program onto your ATmega16.
- Use the oscilloscope to view the signal on the transmit antenna. (Connect the probe to the pad marked TxAnt on the board, or the via on the transmit electrode itself.) You should see sine wave with an amplitude of several tens of volts, or if you're lucky, maybe 100V. The frequency of this wave should be your calculated transmit frequency.
- Now, connect the oscilloscope to the RxOut pin. You should see a sine wave with an amplitude of a volt or two and a DC offset of 2.5V. Experiment with moving your hand closer to the electrodes while the oscilloscope is connected. You should see the amplitude of the receive waveform drop as your hand gets near.
Setting Up and Checking the ADC Timing
- Set up the ADC in free running mode, using the prescaler value you determined. For now, let it continuously run as long as your program is running. Use a resolution of 8 bits.
- Write an ISR for the ADC conversion complete interrupt that briefly pulses an I/O pin (set it high on one line and low again on the next). This provides us with an event that we can easily observe on the oscilloscope without taking too much time. The pulses will occur when a conversion is complete, which is a little bit before the next sample is taken (refer back to the datasheet for the exact timing.) We won't actually do anything with the converted value yet.
- Verify that what you see on the oscilloscope is what you are expecting from your calculations. Each successive pulse should appear 90˚ later in the period of the receive waveform than the previous one.
If you have all of the above working, you should be in good shape for next week's lab, in which we will finish implementing the sensor and add USB communication to and from your PC.
- During the first half-hour of the next lab, demonstrate the circuit that you constructed in part 1.
- During the first half-hour of the next lab, demonstrate that you have a working sensor board and that the amplitude of the received signal changes on the oscilloscope as you move your hand toward and away from the board. You should also demonstrate that the timing of your ADC is correct.
- E-mail your report containing the answers to the questions and all of your calculations to cse466-tas@cs.