21 Adc2

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Analog to Digital Conversion - Part 2

December 2, 2011

1 Introduction

In this lesson, we use the ADC integrated with our MSP430G2231 microcon-
troller to perform a very interesting experiment! Please keep both the processor
manuals at hand while going through this lesson.

2 The LED as a light sensor

The working of an LED as a light source is common knowledge. What is not so


well known is the fact that the LED acts in the reverse direction also - that is,
you shine light onto it and it generates a voltage!

http://en.wikipedia.org/wiki/LED_circuit#LED_as_light_sensor

If you have a multimeter at hand, try this experiment. Measure the voltage
across the LED as you shine bright light onto it at a very short distance using
a torch. I got a voltage reading of about 1.4V when I tried this with a red LED
in transparent casing.
This opens up some interesting possibilities. You can now use the LED as
an inexpensive light sensor!

3 The Experiment

Our Launchpad has two LED's - one connected to P1.0 (red LED) and the other
one connected to P1.6 (green LED). We will measure light intensity using the
RED LED - if it is dark, we will light up the green LED, otherwise, we will put
o the green LED. We will do this continuously in a loop.
[Note: The two LED's on the launchpad board are placed very close to each
other. There is a possibility that this will generate a feedback eect - the light
generated by the green LED may be sensed by the red LED]

1
4 Structure of this lesson

The ADC is a complex peripheral - many things have to be properly initialized


if it is to work as expected. I have written some functions to perform the
initializations (and one or two other things) - this lesson is basically a description
of how these functions actually work. Towards the end, you will be required to
write a main program which will use the already dened functions to perform
the light sensing experiment!

5 The MSP430 ADC10

5.1 Introduction

Our MSP430G2231 has a 10 bit ADC integrated into the chip - it is called
ADC10 in the processor manual. There are 8 channels for ADC10 on the
MSP430G2231. These channels are called A0, A1, ... A7. A channel is
basically a pin which accepts analog voltage input. Our ADC10 is capable
of digitizing inputs from 8 independent external voltage sources - this will be
needed if you are planning to monitor more than one sensor in your applica-
tion (say you need to monitor the voltage outputs from light, temperature and
pressure sensors). Even though the ADC has 8 channels, it is not possible to
digitize data from these channels in parallel - you will have to process data from
the channels sequentially.
There is a small problem here. The MSP430G2231 is a 14 pin device. Out
of these 14 pins, 8 pins are dedicated for PORT1 - they are digital input/output
pins. It is impossible to dedicate a separate set of 8 pins for the ADC input
channels - the solution is to multiplex the digital i/o pins with the ADC input
channels. All the PORT1 pins (P1.0 to P1.7) can act as either digital i/o pins
or ADC input channels. When you wish to use these pins as analog input
channels, you simply have to set some bits in a control register (we will see this
in a moment) and the digital i/o functionality on these pins get disabled - you
can now use them as analog inputs!

5.2 ADC Initialization

[Note: The ADC10 control registers are described in detail starting from page
558 of msp430-family-guide.pdf. Please keep this document at hand while read-
ing this section]
[Note: I would like to repeat that the ADC is a complex peripheral - it
has many dierent modes of operation. It is hard for us to learn in details the
working of each and every mode - we instead focus on selecting the simplest
options wherever possible]

2
5.2.1 Power ON the ADC

The ADC is by default powered OFF (to reduce power consumption). Bit 4 of
the register ADC10CTL0 should be set to 1 to put the ADC in the ON state.
This can be done by doing:

ADC10CTL0 = ADC10CTL0 | (1 << 4)

But, a better way to do this is to write:

ADC10CTL0 = ADC10CTL0 | ADC10ON

In one of the header les included in your program, you will see the symbol
ADC10ON being dened as:

0x10

which in binary has the value:

0 0 0 1 0 0 0 0

That is, a bit pattern whose D4th bit (remember, D0 is the rightmost, least
1
signicant bit) is set to 1 .

5.2.2 Select reference voltage

An ADC needs two reference voltages which will decide its operating range.
Bits 13, 14 and 15 (called SREFx in the manual) of ADC10CTL0 decide how
the reference voltage is selected. If these bits are all zero, then Vr+ (positive
reference voltage) will be Vcc (the supply voltage) and Vr- (negative reference
voltage) will be GND (the supply ground). By changing the values of these bits,
we can choose from many dierent reference voltage sources like:

1. An internal 2.5V or 1.5V reference voltage. The MSP430 controller has


an internal voltage source which generates either 2.5V or 1.5V. We can
chose this for our reference, if needed.

2. We can use voltages applied to two external pins as the refernce voltage

For our purpose, we will choose Vcc and GND as the voltage reference - this is
done by setting all the SREFx bits to 0:

ADC10CTL0 = ADC10CTL0 | SREF_0

If you wish to choose the internal voltage source as your Vr+ (and GND as Vr-),
you can do:

ADC10CTL0 = ADC10CTL0 | SREF_1


1 You may revise the lesson on hardware interrupts if you do not remember our discussion
regarding the use of symbols (like ADC10ON) instead of hard coded numbers in our programs.

3
5.2.3 Select Sample and Hold delay

ADC's are sometimes used for digitizing fast changing signals (say a sine wave-
form of frequency 100Khz). It takes the ADC a nite amount of time to digi-
tize the voltage on its analog input channel - if the voltage on the input channel
varies during this period, the Analog-to-digital conversion process will not work
properly. A circuit called a sample-and-hold
2 is employed to sample the
value on the analog input pin and hold it steady during the time it takes the
ADC to convert it to a binary pattern. Bits 11 and 12 of ADC10CTL0 decide
the sample and hold delay. The delay is expressed as multiples of the ADC clock
time period - we will discuss more about the ADC clock in the coming section.
For example, if bit 12 is set to 1 and bit 11 is cleared to 0, the sample and hold
delay will be 16 times the ADC clock time period:

ADC10CTL0 = ADC10CTL0 | ADC10SHT_2

5.2.4 Select ADC analog input channel

We had seen earlier that all the general purpose I/O pins of PORT1 can also
be used as ADC10 analog input pins. If we wish to digitize the voltage on A0
(pin number 2, multiplexed with P1.0), we have to explicitly instruct the ADC
to select that channel by choosing an appropriate value for the bits 12, 13, 14,
15 of ADC10CTL1 (these bits are called INCHx in the manual). Choosing 0000
as the value of these bits will choose channel A0. In our program, we can write:

ADC10CTL1 = ADC10CTL1 | INCH_0

5.2.5 Select the mechanism used for triggering an AD conversion

The ADC can be made to start digitizing the voltage on its analog input pin
by setting a bit of ADC10CTL0 (called ADC10SC). This is called a software
trigger. For digitizing rapidly varying signals at precise intervals, it would
be better to use a timer. There is a provision for the timer to issue a start
conversion trigger to the ADC. For simple applications, we prefer a software
trigger. When bits 10 and 11 of ADC10CTL1 are both zeros, the ADC10SC bit
of ADC10CTL0 will be used as a start conversion trigger:

ADC10CTL1 = ADC10CTL1 | SHS_0

5.2.6 ADC clock source select

The ADC needs a clock signal for its proper functioning .


3 The MSP430 has
a 5MHz clock internal to it specically for use by the ADC. Bits 4 and 3 of

2 Refer http://en.wikipedia.org/wiki/Sample_and_hold for more details


3 The time taken by the ADC to convert an analog value to a binary pattern depends on
the frequency of this clock. ADC10 takes 13 clock cycles for AD conversion. If the ADC is
using the dedicated 5MHz clock (period = .2 micro seconds), then it takes 6.5 micro seconds
to convert an analog input to its equivalent digital value.

4
ADC10CTL1 (called ADC10SSELx) decide whether we should use this dedi-
cated clock or some other source. The easiest option is to choose the dedicated
clock - this is done by setting ADC10SSELx to 00:

ADC10CTL1 = ADC10CTL1 | ADCSSEL_0

5.2.7 ADC clock division

It is possible to reduce the frequency of the ADC clock by manipulating bits


7, 6 and 5 of ADC10CTL1 (called ADC10DIVx). Choosing a value of 000 for
these bits results in the ADC clock not getting divided:

ADC10CTL1 = ADC10CTL1 | ADCDIV_0

5.2.8 Select conversion sequence

Bits 2 and 1 of ADC10CTL1 (the CONSEQx) bits are used for selecting the
conversion sequence. The easiest option is to set both bits to 0:

ADC10CTL1 = ADC10CTL1 | CONSEQ_0


This will result in selection of single-channel-single-conversion mode, which is
what we need for our simple light sensing application.

5.2.9 Enable analog input

The ADC analog voltage input pins are multiplexed with the General Purpose
I/O port pins (PORT1 pins). If we choose say A0 (corresponding to pin P1.0)
as our ADC input channel, then we have to explicitly turn o the I/O port
functionality on this pin - this is done by setting a bit in a register called
ADC10AE0 - if we set bit D0 (least signicant bit) of this register to 1, channel
A0's digital I/O functionality is disabled, if we set bit D1 of this regiter to 1,
channel A1's digital I/O functionality is disabled and so on for all the other
bits. So, if we wish to enable analog input on A0, we can do:

ADC10AE0 = BIT0
(Note that BIT0 is a symbol whose value is a bit pattern with D0'th bit = 1,
ie, 000000001)

5.2.10 Enable the ADC

The ADC needs to be enabled before we ask it to start the AD conversion


process. This is done by setting Bit 1 of ADC10CTL0 (called ENC):

ADC10CTL0 = ADC10CTL0 | ENC


The manual species that this should be the last step in the initialization pro-
4
cess .
4 It seems that most bits in ADC10CTL0 and ADC10CTL1 can be changed only when
ENC is 0

5
5.2.11 Starting a conversion

Once enabled, the ADC will start digitizing the analog voltage on its selected
input channel when the ADC10SC bit of ADC10CTL0 is set to 1. We will call
this a start of conversion trigger .
5

ADC10CTL0 = ADC10CTL0 | ADC10SC

The ADC10SC bit should be set once again when you wish to do another con-
version.

5.2.12 Checking whether a conversion is over

The ADC takes a denite amount of time (13 clock cycles) to convert its analog
input to the equivalent binary pattern. When the conversion process is over,
the value of the 0th bit of ADC10CTL1 (called ADC10BUSY) will be 0. If you
check the value of this bit during the time a conversion is taking place, its value
will be 1.

5.2.13 Getting the converted data

The output of the AD conversion process is a 10 bit number. This number is


stored in a register called ADC10MEM. You can copy the value in ADC10MEM
to an ordinary C variable and use it for any purpose.

5.2.14 Pseudo-code for a single conversion

Let's say you wish to sample and convert the value on channel A0 just once.
Here is how you do it:

1. Initialize the ADC

2. Generate the start-of-conversion trigger

3. Wait for the conversion to be over

4. Check the value in ADC10MEM - this will hold the 10 bit digital output
of the ADC.

6 A set of C functions

6.1 Initialize ADC10

Here is a function which will set up our ADC10 to digitize data from channel A0
(pin P1.0). The working of this function should be obvious from the discussion
we had in the previous sections.

5 We need not clear the ADC10SC bit - it gets automatically cleared!

6
void adc_init()
{

ADC10CTL0 = ADC10ON | ADC10SHT_2 | SREF_0;

ADC10CTL1 = INCH_0 | SHS_0 | ADC10DIV_0 | ADC10SSEL_0 | CONSEQ_0 ;


ADC10AE0 = BIT0;

ADC10CTL0 |= ENC ;
}

6.2 Start Conversion

Here is a function which will trigger the Analog-to-digital conversion process:

void start_conversion()
{
ADC10CTL0 |= ADC10SC;
}

6.3 Check whether conversion is over

Here is a function which will check whether AD conversion is over:

unsigned int converting()


{
return ADC10CTL1 & ADC10BUSY;
}

This function simply returns the value of the busy bit of ADC10CTL1 - if the
value returned is 1, it means the ADC is busy - it is still doing the conversion
process.

7 Implementing the LED-as-a-sensor application

The red LED is connected to P1.0 (ADC channel A0 - note that our ADC
initialization functions sets up the ADC to sample from A0). Our objective
is to write a program which will use this LED as a light sensor. When this
LED is brightly illuminated (by say keeping a torch very near to it), a potential
dierence of about 1.4V develops across its leads - we can use ADC10 to measure
this voltage.
The ADC initialization function given above initializes ADC10 in such a
way that Vr+ (positive voltage reference) is Vcc (which is about 3.6V for the
launchpad board) and Vr- (negative voltage reference) is GND (0V). This means
that our 10 bit ADC operates in the range 0 to 3.6V. If the input voltage is 0V,
the ADC generates a 10 bit value:

7
0 0 0 0 0 0 0 0 0 0
which is numerically equal to 0. When the input voltage is 3.6V, the ADC
generates a 10 bit pattern:

1 1 1 1 1 1 1 1 1 1
which is numerically equal to 1023.
Now, when the RED LED comes under maximum illumination, it develops
a potential dierence of about 1.4V - what is the digital output generated by
the ADC for an input voltage of 1.4V? The calculation is simple:

1023 * (1.4/3.6)
which is equal to 397.8.
Now, here is what you have to do. Write a program which when executed
will light up the GREEN LED whenever the RED LED is not under bright light.
Keep the launchpad board away from bright sunlight and the GREEN LED will
be ON. Now, bring a torch (I am using the torch on my mobile!) very close to
the RED LED (directly above it) and the GREEN LED should go OFF. Put
o the torch and the GREEN LED should come ON again.
Here are some hints for you, based on the code I wrote:

1. I used a cut-o value of 380 for the ADC reading in my code and it is
working ne

2. Use a small delay loop (say 1000 iterations) in between successive ADC
readings ... my code did not work without this loop
6

3. Because both the RED and GREEN LED's are close to each other, you
can expect an interesting feedback eect when you run the code!

4. Use the functions dened in the previous sections in your main program

5. The ADC needs to be initialized only once

6. Each ADC conversion requires a start-of-conversion-trigger

7. You have to make sure that AD conversion is complete before you check the
value in ADC10MEM. Use the function converting dened in a previous
section to do this - this function should be called repeatedly in a loop until
it returns 0.

Post your code on github!

8 Additional Exercise

Is it possible to write a program which will use the same LED as both the light
sensor as well as the light output element? Try it!

6I am still trying to nd out why this loop is required!

8
9 Test

There is no test paper associated with this lesson!

You might also like