TI MSP-EXP430G2 LaunchPad

One of my friends asked me to help write some code for a project she was working on using the Texas Instruments MSP-EXP430G2 LaunchPad board. The requirements were as follows:

1. The program was to be written in the Energia IDE (very similar to the Arduino/Processing IDE).
2. The LEDs need to illuminate and extinguish in intervals of 30ms followed by a 1 second pause.
3. The microcontroller needs to get the internal temperature sensor reading and display it using the LEDs on the LaunchPad
3a. The RED LED will blink the tens digit
3b. The GREEN LED will blink the ones digit
4. After the temperature is displayed, the system should pause for 1 second
5. The button on the LaunchPad should allow the user to switch between the temperature displayed in Fahrenheit and Celsius, with Fahrenheit being the default.
6. This sequence should run continuously

I found a reference to reading the internal temperature sensor value HERE which helped me get started on the program. I though this program was going to be a piece of cake… but I quickly discovered I couldn’t have been more wrong! First came the problem of getting the calibration data out of the ROM of the microcontroller. I had never tried to directly access a ROM register before (usually they are predefined). I followed some examples I found but we kept getting erroneous results. After much troubleshooting I realized that I could only read the registers once; if I attempted to read them again I would be returned bad results.

Now that we had the calibration data out of the way, we had to play around with calculating the actual temperature from the calibration points and provided formulas that can be found in the microcontroller’s datasheet. We kept getting temperature readings that were far above ambient room temperature. I knew this couldn’t be right so I had my friend put the entire board in the freezer for about 15 minutes. She then powered up the board and opened the serial console and we were still getting the same result.

This is where the real fun began.

At this point I was about to give up. I wasn’t familiar with the IDE, or the development platform (oh, and I forgot to mention that my friend lives in a whole different time zone, and we were communicating over Twitter!). I was getting really frustrated and decided to take a break and look at it again the next day. The next day, using the Arduino IDE as my guide, I started to dig around the backend files of the Energia IDE to figure out what was going on. In the microcontroller datasheet it said Analog Input 10 was tied to the temperature sensor, and so we were trying to do an analogRead(10) but kept getting incorrect results every time. Finally I tracked down where the IDE defines the analogRead() function and discovered something quite curious (found in wiring_analog.c):

 

NOTE: All of these files are located somewhere within the /hardware/msp430/ folder!

 

uint16_t analogRead(uint8_t pin)
{
// make sure we have an ADC
	uint8_t channel;
 
	// Check if pin is valid
	if (pin==NOT_ON_ADC)
		return 0;
	// Check if pin is a special analog pin (A10 = temp sensor, A11 = Vcc/2, etc.)
	if (pin >=128)
		channel = pin - 128;
	else
		channel = digitalPinToADCIn(pin);
 
#if defined(__MSP430_HAS_ADC10__) || defined(__MSP430_HAS_ADC10_B__) || defined(__MSP430_HAS_ADC12_PLUS__) || defined(__MSP430_HAS_ADC12_B__)
    //  0000 A0
    //  0001 A1
    //  0010 A2
    //  0011 A3
    //  0100 A4
    //  0101 A5
    //  0110 A6
    //  0111 A7
    //  1010 Internal temperature sensor
 
    //TODO: Only int. temp. sensor requires Tsample > 30us.
    // The below ADC configuration applies this rule to all channels right now.
    // ADC10CLK = 5MHz / 5 = 1Mhz
    // Tsample = S&H / ADC10CLK = 64 / 1 MHz = 64 us
    // Tconvert = 13 / ADC10CLK = 13 / 1 MHz = 13 us
    // Total time per sample = Tconvert + Tsample = 64 + 13 = 67 us = ~15k samples / sec

Found in Energia.h

#define digitalPinToADCIn(P)      ( digital_pin_to_analog_in[P] )

 

Found in pins_energia.h

const uint32_t digital_pin_to_analog_in[] = {
        NOT_ON_ADC,     /*  dummy   */
        NOT_ON_ADC,     /*  1 - 3.3V*/
        0,				/*  2 - A0 */
        1,     			/*  3 - A1 */
        2, 				/*  4 - A2 */
        3, 				/*  5 - A3 */
        4, 				/*  6 - A4 */
        5,   			/*  7 - A5 */
        NOT_ON_ADC, 	/*  8 - P2.0 */
        NOT_ON_ADC, 	/*  9 - P2.1 */
        NOT_ON_ADC, 	/*  10 - P2.2 */
        NOT_ON_ADC, 	/*  11 - P2.3 */
        NOT_ON_ADC, 	/*  12 - P2.4 */
        NOT_ON_ADC, 	/*  13 - P2.5 */
        6,     			/*  14 - A6 */
        7,     			/*  15 - A7 */
        NOT_ON_ADC, 	/*  16 - RST */
        NOT_ON_ADC,     /*  17 - PF0 */
        NOT_ON_ADC, 	/*  18 - PE0 */
        NOT_ON_ADC,     /*  19 - PB2 */
        NOT_ON_ADC  	/*  20 - GND */
};

 

Huh, that is interesting that pins_energia.h doesn’t even list analog input 10!

So looking at this code the first thing it does is check to see if the pin is legitimate by seeing if the pin variable is set to “NOT_ON_ADC”… But wait a second! The pin variable would never be “NOT_ON_ADC” because it is further down in the code when it calls to the digitalPinToADCIn() function to check to see if the user provided pin is legitimate!

Ah ha!

So what was happening was that the 10 we were passing to analogRead() was falling into the “else” statement, getting reset from 10 t0 “NOT_ON_ADC” and then asking the microcontroller to process that variable as a legitimate analog input pin… Needless to say it wasn’t pretty! So how could I get around this? Modify the wiring_analog.c file? Modify the pins_energia.h file? Neither, because I could exploit the if(pin >= 128) statement! All I had to do was add 128 to the pin number (aka 128 + 10 = 138) and I could get the back end code to skip over doing the whole legitimate pin check and go about its business with the correct pin number!

Bingo! It worked.

I was very relieved to see the code start to function properly. The temperature readings it was giving back to us were 1 or 2 degrees off, but that is expected due to internal heating of the microcontroller.

Here is my final code:

https://github.com/Echoskope/MSP-EXP430G2/blob/master/main.c

 

 

 

 

 

 

Leave a Reply

© 2014 - Brain Overload. All Rights Reserved. Powered by Wordpress and Design by We Create Web Designs