Professional Documents
Culture Documents
21 Adc2
21 Adc2
21 Adc2
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.
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
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!
[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:
In one of the header les included in your program, you will see the symbol
ADC10ON being dened as:
0x10
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 .
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:
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:
If you wish to choose the internal voltage source as your Vr+ (and GND as Vr-),
you can do:
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:
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:
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:
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:
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:
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
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
The ADC10SC bit should be set once again when you wish to do another con-
version.
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.
Let's say you wish to sample and convert the value on channel A0 just once.
Here is how you do it:
4. Check the value in ADC10MEM - this will hold the 10 bit digital output
of the ADC.
6 A set of C functions
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.
6
void adc_init()
{
ADC10CTL0 |= ENC ;
}
void start_conversion()
{
ADC10CTL0 |= ADC10SC;
}
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.
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
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.
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!
8
9 Test