Scientific Instruments Using The TI MSP430

First: how can we minimize any delay in the timing resulting from delays from carrying out instructions? If we’re not careful, a non-negligible amount of time can pass between when we start the capacitor discharge and the timer, or between the comparator trigger and the timer capture.

Second: how do we determine what capacitances could be measured for a given configuration? Smaller capacitors will discharge more quickly, resulting in shorter measurement times (meaning more error due to the digital nature of the timer). Larger capacitors take more time to charge up, and will not be fully charged once we start discharging.

The first issue is well resolved by using features built into the Timer_A module. The second is less easily resolved, but easily understood, so we will know prematurely the constraints of our code. There are a couple of things we’ll be able to do to improve it generally, but for our purposes here we won’t be too concerned about it.

New Feature of the Timer_A Module: Output

Let’s introduce here two features in Timer_A we haven’t used yet. First off, let us take a look at how we can use the timer to change an output. Recall that the Timer_A module has a certain number of “capture/compare” registers built into each MSP430 device. (The G2211 and G2231 have two.) Each of these registers can drive their very own output; we can program the MSP430 to regulate the output every time the timer reaches the value stored in the register. For instance, we will set the output TA0.1 to set the output (to 1, that’s) every time the timer reaches the worth set in TACCR1. Or we can toggle the output TA0.0 every time the timer reaches the worth set in TACCR0. We even have modes that allow us to make use of both registers on the identical output, giving one result at TACCR1 and another at TACCR0. (This ability is used for pulse width modulation, or PWM. We’ll speak about that in an upcoming tutorial!)

Take a look at table 12-2 in you x2xx Family User’s Guide:

This table lists all the possible modes we can use to work with the timer outputs.

New Feature of the Timer_A Module: Capture

To date we’ve got only discussed uses of the timer in compare mode. The opposite mode, capturing, can be utilized to do precise timing of events. In capture mode, the timer records the value in TAR into TACCRx at the moment when the capture is triggered. This trigger can come externally, or it could actually come from internal connections to other modules, including the comparator. By configuring the timer in this way, we are able to record the timer value when the comparator output provides either a rising edge (going from 0 to 1) or a falling edge (from 1 to 0).

Putting All of it Together

This is the general concept used within the capacitance meter. Note that accurate timing requires a calibrated clock, so we’ll use the calibrated 1 MHz DCO for this project. First, we connect the resistor to a timer output. (For this purpose, we’ll use the TA0.0 output.) The junction between the resistor and capacitor is tied to a comparator input, and the opposite end of the capacitor is connected to ground. We start charging the capacitor by setting TA0.0, and wait some specified period of time for the capacitor to charge. The output is then reset (grounded) at the time specified in TACCR0. While the capacitor’s voltage is above the reference voltage, the output is about at 1 (assuming we tied the RC circuit to V+ and the reference to V-). When it drops below that value, the comparator output falls, triggering a capture in the timer, recorded in TACCR1. The difference in time between TACCR1 and TACCR0 is an accurate measurement of the decay time of the RC circuit from Vcc to Vref. (Note that if TACCR0 is 0, no subtraction is needed.)

Obviously the longer the time it takes to fall, the more accurate our timing measurement will be overall. But what happens if the time is longer than 2^16 microseconds? TAR rolls over, and starts counting over again; so in our code, we’ll need to account for any rollovers which will occur.

Let’s examine the comparator configuration used within the code:

void CAinit(void)
CACTL1 = CARSEL + CAREF_1; // 0.25 Vcc ref on – pin.
CACTL2 = P2CA4 + CAF; // Input CA1 on + pin, filter output.
CAPD = AIN1; // disable digital I/O on P1.1 (technically
// this step is redundant)
// CAinit

This sets up the comparator to use CA1 on the V+ input. If you happen to check the MSP430G2211 datasheet, CA1 is connected to P1.1. Looking up the register description within the Family User’s Guide, we configure for CA1 on V+ by setting P2CA4. (P2CA0 also controls V+, and for CA1 needs to be clear.)

Now let’s look at the timer configuration:
void TAinit(void)
TACTL = TASSEL_2 + ID_0 + MC_0; // Use SMCLK (1 MHz Calibrated), no division,
// stopped mode
TACCTL1 = CCIS_1 + SCS + CAP + CCIE; // Use CAOUT for input, synchronize, set to
// capture mode, enable interrupt for TA1.
// NOTE: Capturing mode not started.
// TAinit

The timer is arrange without starting. Setting TACCTL0 to OUTMOD_1 sets the output TA0.0 when TAR reaches TACCR0, which is 0 by default. Enabling the interrupt lets us keep track of overflows. In TACCTL1, we alter to capture mode by setting CAP. To know how to attach the comparator, we need to check the device datasheet. Find the table called “TIMER_A2 SIGNAL CONNECTIONS” and make sure you are looking at the one specific to devices with COMP_A+. Within the Device Input Signal column, find CAOUT (internal), and note the Module Input Name in the column next to it: CCI1B. The CCISx bits in TACCTLx select the input, and in the Family User’s Guide, we see that these two bits should be set to 0b01 to select CCIxB. In the device’s header file, we discover that we are able to set these bits with CCIS_1.

Also note that by setting SCS, we synchronize the capture to the timer clock. We haven’t started capturing yet, just as we haven’t started the timer. The code is about as much as anticipate the user to push the button connected to P1.3. Doing so exits LPM0, and continues the primary code. The following then happens:
First, the timer is turned on. When the timer rolls over the first time, TA0.0 (on P1.5 in this code) is about, charging the capacitor. We wish to wait long enough for the capacitor to charge. The code is set to look ahead to 10 overflows, which corresponds to about 655 ms. At this point, the comparator is turned on, and the timer is configured to reset TA0.0 at the next overflow (so we have actually charged for 11 overflows at this point). We let the timer capture the subsequent event, or when the voltage on the capacitor (on P1.1/CA1) drops to the worth at Vref, or 1/4 Vcc. At this point, an interrupt is triggered. The interrupt routine turns off the captures and the timer and returns to the primary code. The code loops back, and starts the method again, waiting for the user to press the button to begin a measurement.

Note: Before running the code as set up, keep in mind we’re using P1.1; what else is that this pin used for? You may wish to remove the TXD jumper to get the project to work properly. Thanks to RobG over at for pointing this out to me… I was really puzzled by it for an embarrassingly very long time!

Try running the code present in CMeterG2211.c. To do this, you will need a resistor and a capacitor. Use a ten kO resistor and a 100 nF capacitor (it may have a label that says 104 on it) if you can. In the debugger, set the code to run freely, and push the button. The led should switch from green to red, then back to green, indicating the measurement is finished. The timer has captured the event and recorded the time in TACCR1. Unfortunately, there’s no option to see this as is yet! Pause the debugger, and examine the timer_a2 registers. The time is recorded in TACCR1. For the suggests RC combination, it’s best to have a value somewhere around 1400. (You possibly can change from the default hex format to decimal by right-clicking the register and selecting decimal in the format menu.)

Try increasing R to 100 kO. You must see the time increase by an element of 10. Try using a 1 uF capacitor. (You might need to increase the variety of overflows to attend while charging to get something accurate here.) In the watch window, we can view the value within the overflows variable. To do that, click where the window says , and sort in the variable name. With such a big capacitor, it’s best to see the variety of times the timer wrapped around before stopping. With the measured time and the known resistor value, you have to be able to make use of the formula provided in the previous tutorial to calculate the worth of the capacitor. Be at liberty to experiment with this program. Particularly, how consistent are your timing measurements?

Apart from the lack of ability to see the timer value without using the debugger, there are a couple of issues to work out still in this meter. We’ll take a careful look at some of these sooner or later, and bring back this code to demonstrate ways we will see data and ways we are able to improve the timer.

Reader Exercise: Given the discussion within the previous tutorial about the accuracy of the meter, and from your individual experimentation with this system, where are the key sources of error within the measurement? How consistent is the timing? What might cause the inconsistency? What assumptions have we made in the way we measure the capacitance? Once you have built an instrument to make any sort of scientific measurement, it is important to identify all of these aspects. By doing so, we identify the constraints of the instrument, both those we will fix and people we have to live with.

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *