You are on page 1of 7

ECEN 403 Mini Project Part 3 PWM Page 1 of 7

Lab 2: Analog-to-Digital Conversion and Pulse Width Modulation


for the TI Stellaris Launchpad

The tools and concepts covered in this example are:
- Configuring the ADC12 using clocks, timers and/or interrupts;
- PWM
Caution: Ensure adequate time is utilized to properly comprehend what is
accomplished in each section of the lab rather than skimming or skipping. Your
hard work will be rewarded. Understanding clocks, timers, interrupts, and the
ADC are vital to understanding and implementing pulse width modulation.

Required Documents for this lab:
- LM4F120H5QR Data Sheet and Users Guide
http://www.ti.com/lit/ds/spms351b/spms351b.pdf
- Stellaris Workshop Manual
http://software-dl.ti.com/trainingTTO/trainingTTO_public_sw/GSW-Stellaris-
LaunchPad/StellarisLaunchPadWorkbook.pdf
- ARM Optimizing C/C++ Compilers User Guide
http://www.ti.com/lit/ug/spnu151i/spnu151i.pdf
- BoosterPack Development Guide
http://www.ti.com/lit/ug/spmu288/spmu288.pdf
There are some useful documents that you should have available in
C:\StellarisWare\docs and find:
- Peripheral Driver Users Guide (SW-DRL-UGxxxx.pdf)
- USB Library Users Guide (SW-USBL-UGxxxx.pdf)
- Graphics Library Users Guide (SW-GRL-UGxxxx.pdf)
- LaunchPad Board Users Guide (SW-EK-LM4F120XL-UG-xxxx.pdf )

References:
How Analog-to-Digital Converter (ADC) Works by Gabriel Torres
http://www.hardwaresecrets.com/article/317
Using PWM Output as a Digital-to-Analog Converter with a Low Pass Filter
http://www.ti.com/lit/an/spraa88a/spraa88a.pdf
Introduction to Pulse Width Modulation/
http://www.embedded.com/electronics-blogs/beginner-s-
corner/4023833/Introduction-to-Pulse-Width-Modulation
Pulse-Width Modulation
http://fab.cba.mit.edu/classes/MIT/961.04/topics/pwm.pdf
ECEN 403 Mini Project Part 3 PWM Page 2 of 7


Analog to Digital (A/D) Conversion
Most engineering applications necessitate measurements, controls, calculations,
communications, and data storage. For the microcontroller to translate a physical
signal between an analog environment (e.g., Temperature, humidity, barometric
pressure, etc.) to digital; data handling requires an analogue-to-digital converter
(ADC). Nyquist theorem controls the signal sampling time interval (frequency) to
convert the analog signal into a digital signal and reproducing amplitude variants.
An analog to digital converter (ADC) takes analog voltage and converts it into
discrete digital quantities. ADC includes 8-bit, 10-bit, and 12-bit converters. How
many bits does the TI Stellaris ADC cover? A/D conversion works on the principle
of bits:
8 bits: 2^8 = 256 discrete quantities
10 bits: 2^10 = 1024 discrete quantities
12 bits: 2^12 = 4096 discrete quantities

An important element in A/D conversion is the reference voltage. If an input signal
voltage is greater than the ADC reference voltage then the signal will be clipped. If
the input signal exceeds VCC on one MCU port, the microcontroller will burn.
With microcontrollers values for the ADC are referenced with the integer number
system. A 12-bit ADC has (0 4095) 4096 discrete quantities. For example
convert 2.35V to a digital number. First program the MCU to sample the voltage
on one of the A/D pins. If the MCU uses 12-bit conversion, the MCU gives the
conversion result as 2915. What does this mean? For a VREF of 3.3V and have a
(0-4095) data sample range for 12-bit conversion. Starting at the 2915 result and
take the ratio 2915/4095=0.711. Now take 0.711*VREF = 0.711*5V = 2.346 V.
Notice 2.346V is close to 2.35V but not exact. Why is the voltage off? A/D
conversion resolution is the conversion step size. With 12-bit conversion and
sample number value of 1000 then the voltage is 1000/4095 = 0.2442 and
0.244*3.3V = 0.8058V. Now increase one-step in signal digitization and
1001/4095 = 0.2444, then 0.2444*3.3V = 0.8066 V. So, 0.8066V (step 1001)
0.8058V (step 1000) = 0.8 mV. Therefore ADC resolution is at 0.8 mV per step
and explains why 2.346V was detected instead of 2.35V.

Pulse Width Modulation
ECEN 314 discussed sampling theory as the connection between two worlds
analog continuous time signals (CTS) and digital discrete time signals (DTS).
There are two different methods for presenting the same analog signal. CTS
sampling yields a sequence of impulses; DTS presents CTS information as a
sequence of numbers. The first half of the lab took a sampled CTS and produced a
ECEN 403 Mini Project Part 3 PWM Page 3 of 7

sequence of numbers representing the MCU temperature. The second half will take
sampled CTS and yield a sequence of impulses.

A continuous analog signal has infinite resolution in both time and magnitude and
constantly changes its value. Digital signals are distinguishable from analog signals
because the former employs values exclusively from a set of predetermined
possibilities such as {0V, 5V} or a voltage or current source delivered to an analog
load by a repeating series of high and low pulses. High represents the on-time
period the source supplies the load and low occurs when the source is switched off.
The longer the on-time compared to the off-time translates to increasing voltage
and current supplied to the load. Blending or converting analog and digital signals
is accomplished through sampling theory. For example, when an analog CTS is
sampled then the sampled values amend amplitude, width, or position of the
periodic impulse train. This sampling theory application is termed Pulse width
modulation (PWM). PWM digitally encodes analog signals by changing a periodic
impulse width. The PWM signal is digital because at any time instant the impulse
is either high or low. PWM is a commonly utilized technique in embedded
microprocessing for controlling analog circuits through DTS adequately without
requiring a digital to analog converter and appreciated in applications ranging from
measurement and communications to power control and conversion.

PWM is quite simple, as shown in Fig. 2.1. A PWM signal comprises the period or
time of each pulse and duty cycle or the period percentage the impulse signal is
high or low. In essence, the load supply or reception alternates on and off
periodically so the average voltage has the desired value during a specific time
period. Duty cycle (D) relates the fraction of on-time to the interval time period as
shown in Eq. (2.1). An impulse has either VCC or 0. Duty cycle is expressed in
percent with 100% being fully on. Vary D by holding the period constant and
changing the pulse width, hence PWM.

Eq. (2.1)








ECEN 403 Mini Project Part 3 PWM Page 4 of 7





Fig. 2.1. Basic PWM and duty cycle.

Exercise 2.1: Drive a PWM output using different duty cycles
In this exercise we will be setting set up four PWMs with configurable duty cycles
(20%, 60%, 40% and 80%).
/*
* main.c - PWM Lab
*
* Note from the datasheet:
* In PWM mode, timers are configured as 24-bit or 48-bit down-counter with assigned
start value (corresponding to period) defined by GPTMTnILR and GPTMTnPR registers.
*/

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"

int main(void)
{
unsigned long ulPeriod; // sets the period, and thus frequency, of our PWM
unsigned long dutyCycle1, dutyCycle2, dutyCycle3, dutyCycle4;


// Configures to drive 400 MHz PLL by sys_clk -> 16 MHz xtal
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAI
N); //Set clock speed = 40MHz


/* Configure specific GPIO pins to use the CCP pins associated with certain
timers.
* More info about GPIO pin options in Table 10-2 of Datasheet.
**/
// Enable the GPIO ports where our CCP GPIO pins are
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // Enable the GPIO port
containing the T0 CCP0 and CCP1 pins
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // Enable port F, containing T1
CCP0, CCP1


/* Reference: DataSheet - 1.3.4.4 CCP Pins (under Architectural Overview)
ECEN 403 Mini Project Part 3 PWM Page 5 of 7

* CCP Pins can be used by GPTM (see Lab 4 in the workbook) to time/count
external events with CCP pin as input. GPTM can also generate a PWM output on CCP
pin.
* For PWM, the GPTM is incremented (or decremented) by system clock. The
PWM signal (which is output) is generated based on match between counter value and
value stored in match register.
*/
// Configure pins PB6, PB7 as Timer_0 CCP0, CCP1
// Configure pins PF2, PF3 as Timer_1 CCP0, CCP1

GPIOPinConfigure(GPIO_PF2_T1CCP0); // Configure pin PF2 as Timer 1_A output
GPIOPinConfigure(GPIO_PF3_T1CCP1); // Configure pin PB3 as Timer 1_B output
GPIOPinConfigure(GPIO_PB6_T0CCP0); // Configure pin PB6 as Timer 0_A output
GPIOPinConfigure(GPIO_PB7_T0CCP1); // Configure pin PB7 as Timer 0_B output
/* Note that if you get errors here, you may have to replace the named terms
for actual hex address, found in header file. */

GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_2 ); // Enable pin PF2 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_3 ); // Enable pin PF3 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6 ); // Enable pin PB6 as output of
timer addressed to it
GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_7 ); // Enable pin PB7 as output of
timer addressed to it

// SysCtlClockGet() will give you the number of clock cycles in 1 second. This
is convenient for directly converting to clock frequency division, as one second
corresponds to one Hertz.
ulPeriod = (SysCtlClockGet() / 500)/2;
dutyCycle1 = (unsigned long)(ulPeriod-1)*0.8;
dutyCycle2 = (unsigned long)(ulPeriod-1)*0.6;
dutyCycle3 = (unsigned long)(ulPeriod-1)*0.4;
dutyCycle4 = (unsigned long)(ulPeriod-1)*0.2;

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); // Enable Timer 1
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // Enable Timer 0

// Configure the timers as split 16-bit pairs, and set each timer as PWM mode.
TimerConfigure(TIMER1_BASE,
(TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM));
TimerConfigure(TIMER0_BASE,
(TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM));

TimerControlLevel(TIMER1_BASE, TIMER_BOTH, 0); // Timer 1 is trigger low
TimerControlLevel(TIMER0_BASE, TIMER_BOTH, 0); // Timer 0 is trigger low

// For simplicity, we don't use PWM interrupts, for which we would need to
configure the TnEVENT field in GPTMCTL and eanble

// For simplicity, we don't use prescaler load and match set here.
// If we do use prescaler, the API functions would write value to GPTM Timer n
Prescale Reg (GPTMTnPR)

ECEN 403 Mini Project Part 3 PWM Page 6 of 7

// These API functions load the timer start value into Timer n Interval Load
Reg (GPTMTnILR) Reg 10, 11

// Timer 0 Load set
TimerLoadSet(TIMER1_BASE, TIMER_A, ulPeriod -1);
TimerLoadSet(TIMER1_BASE, TIMER_B, ulPeriod -1);

// Timer 0 Load set
TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1);
TimerLoadSet(TIMER0_BASE, TIMER_B, ulPeriod -1);

// These API functions load the match value into Timer n Match register
(GPTMTnMATCHR)

// Timer 1 Match set
TimerMatchSet(TIMER1_BASE, TIMER_A, dutyCycle1);
TimerMatchSet(TIMER1_BASE, TIMER_B, dutyCycle2);

// Timer 0 Match set
TimerMatchSet(TIMER0_BASE, TIMER_A, dutyCycle3);
TimerMatchSet(TIMER0_BASE, TIMER_B, dutyCycle4);

/* Timers are now configured. */

// Finally, enable the timers, which will now run (API functions will set TnEN
bit in Reg 4 (GPTMCTL)
TimerEnable(TIMER1_BASE, TIMER_BOTH);
TimerEnable(TIMER0_BASE, TIMER_BOTH);


// Continuous while loop, and Timers will be counting in PWM mode
while(1)
{
}
}

Question: Explain the purpose of each header file given in the code.
First Project
Complete Lab 5: ADC12 in the Stellaris Workshop Manual (see required
documents) and successfully demonstrate MCU temperature in degrees Fahrenheit.
You do not need to demonstrate Hardware averaging and Calling APIs from ROM
(i.e. complete all 29 steps outlined in the lab). You can also find a video lecture on
the lab on: http://www.youtube.com/watch?v=XqNAALjC5-k



ECEN 403 Mini Project Part 3 PWM Page 7 of 7

Second Project
This project is essentially an extension of the First project. Similar to the first
project, you will store the ADC values from the data provided by the on-chip
temperature sensor. However, you will instead use interrupts rather than burn CPU
cycles waiting for the ADC conversion to complete (aka the better way
mentioned in step 19 from Lab 5:ADC12 in the Stellaris Launchpad workbook).
Third Project
You will configure the ADC0 module for a single sample from a sine wave or
square wave input source from the function generator. The input waveform will be
sampled by the ADC through a GPIO pin.
Additionally, print out both the raw ADC12 values and the voltage readings in mV
in a UART terminal via PuTTy or a similar program. Note: mV requires no
decimal points. Courtesy: Lucas Kimble
(Extreme Hints: To do this you will configure the GPIO pin specifically as an input
to the ADC i.e. reference gpio.h and gpio.c. You will also need to select the proper
input in your ADC API function calls.)
Fourth Project
Complete the PWM based Exercise 2.1 and answer the question immediately
following it.
Fifth Project
This project will be based on what you have learned and made in this and the
previous lab. Using clocks, timers, interrupts and ADCs generate an output PWM
signal and modulate its duty cycle according to the values input from your ADC.
Restrict your PWM duty cycle to 25% - 75%. To do this, you will need to convert
your ADC readout before setting it as duty cycle.

BONUS!! :- Additionally, use your ADC readout to drive four LED color states.
The lowest 25% of the ADC input voltage range will correspond to a Red LED.
The next quartile will correspond to a Green LED, the third quartile will
correspond to a Blue LED and the last quartile will correspond to a combination of
multiple LEDs. You can choose any LED colors you like (look up Figure 13-9 for
the voltage conversion chart). Courtesy: Arnold Zhang

You might also like