This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430G2553: Flex

Part Number: MSP430G2553


Tool/software: Code Composer Studio

Hello, I am having trouble with sensing the resistance and flex angle of a flex sensor, I do have code for a ohmeter but I am having trouble to create the sensing of resistance and the flex angle my circuit is a basic volt divider with the flex sensor to the output A4 and a resistor toward ground. The voltage source is connected to the flex sensor. I am trying to display resistance and the flex angle

Here is current code that I have:

#include <msp430.h>
#include <stdint.h>
#include <stdio.h>

const float VCC=4.98;
const float R_div=47500;
const straight_resistance= 37300;
const bend_resistance= 90000;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set MCLK and SMCLK to 1MHz
DCOCTL = CALDCO_1MHZ; // Set MCLK and SMCLK to 1MHz

////// Serial port back channel setup

P1SEL = BIT1 + BIT2; // Select UART as the pin function
P1SEL2 = BIT1 + BIT2;
UCA0CTL1 |= UCSWRST; // Disable UART module for configuration
UCA0CTL0 = 0x00; // No parity, LSB first, 8-bit data, 1 stop bit, UART, Asynchronous
UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK source, keep in reset state
UCA0BR0 = 104; // 9600 Baud rate - Assumes 1 MHz clock
UCA0BR1 = 0; // 9600 Baud rate - Assumes 1 MHz clock
UCA0MCTL = 0x02; // 2nd Stage modulation = 1, Oversampling off
IE2 = 0x00; // Interrupts disabled
UCA0CTL1 &= ~UCSWRST;
// Analog setup
ADC10CTL1 = INCH_4 + ADC10DIV_3; // Temperature Sensor and ADC10CLK/4
// ADC set up parameters
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
__delay_cycles(10000); // required for settling of ADC

while(1)
{
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start with interrupt
__bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled, sleep until interrupt
unsigned long flexADC = ADC10MEM;
int flexV = flexADC*VCC /1023;
int flexR = R_div * (VCC / flexV - 1);

// oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
// data shows up magically in ADC10MEM
serial_string("Resistance");


serial_number(flexADC);

}
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}


// The following functions allow us to write strings and numbers to our PC through the back channel uart.
void serial_charTX(char c)
{
while( !(IFG2 & UCA0TXIFG) ); // Wait until the transmit buffer is empty
UCA0TXBUF = c; // Send the character through the Xmit buffer
}

char serial_charRX(void)
{
while( !(IFG2 & UCA0RXIFG) ); // Wait until a character has been received
return UCA0RXBUF; // Return received character
}

void serial_string(char string[])
{
int i;
for(i = 0; string[i] != '\0'; i++) // Send characters until end-of-string
{
if(string[i] == '\n') // The terminal program recognizes \r as the carriage return
serial_charTX('\r');
else
serial_charTX(string[i]);
}
}

void serial_number(int value)
{
char string[10];

sprintf(string, "%d", value); // Convert an integer to a character string

serial_string(string);
}

Here is the Arduino code version of it but I need it in C code.

const int FLEX_PIN = A0; // Pin connected to voltage divider output

// Measure the voltage at 5V and the actual resistance of your
// 47k resistor, and enter them below:
const float VCC = 4.98; // Measured voltage of Ardunio 5V line
const float R_DIV = 47500.0; // Measured resistance of 3.3k resistor

// Upload the code, then try to adjust these values to more
// accurately calculate bend degree.
const float STRAIGHT_RESISTANCE = 37300.0; // resistance when straight
const float BEND_RESISTANCE = 90000.0; // resistance at 90 deg

void setup() 
{
  Serial.begin(9600);
  pinMode(FLEX_PIN, INPUT);
}

void loop() 
{
  // Read the ADC, and calculate voltage and resistance from it
  int flexADC = analogRead(FLEX_PIN);
  float flexV = flexADC * VCC / 1023.0;
  float flexR = R_DIV * (VCC / flexV - 1.0);
  Serial.println("Resistance: " + String(flexR) + " ohms");

  // Use the calculated resistance to estimate the sensor's
  // bend angle:
  float angle = map(flexR, STRAIGHT_RESISTANCE, BEND_RESISTANCE,
                   0, 90.0);
  Serial.println("Bend: " + String(angle) + " degrees");
  Serial.println();

  delay(500);
}
  • What result are you getting now?

    1) Don't forget to set the AE register. This turns off the Schmitt Trigger so you can get (analog) values between "low" and "high". For A4, this would be:

    > ADC10AE0 |= (1 << 4);  // Set A4 as analog input

    2) I think "flexV" will end up as a fraction, and thus truncated when the arithmetic result is cast to "int". This should probably be "float" as well. I suspect you can get away with keeping flexR as "int".

  • New code, however whenever I try to bend my flex sensor, it keeps showing an angle of -63 degrees

    #include <msp430.h>

    #include <stdint.h>
    #include <stdio.h>
    #include "serial_msp.h"

    const float VCC = 4.98;
    const float R_div = 47500;
    const float straight_resistance = 0;
    const float bend_resistance = 320000;

    float map(float value, float fromLow, float fromHigh, int toLow, int toHigh)
    {
    return (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow;
    }


    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT

    DCOCTL = 0; // Select lowest DCOx and MODx settings
    BCSCTL1 = CALBC1_1MHZ; // Set MCLK and SMCLK to 1MHz
    DCOCTL = CALDCO_1MHZ; // Set MCLK and SMCLK to 1MHz
    serial_init();

    /*////// Serial port back channel setup

    P1SEL = BIT1 + BIT2; // Select UART as the pin function
    P1SEL2 = BIT1 + BIT2;
    UCA0CTL1 |= UCSWRST; // Disable UART module for configuration
    UCA0CTL0 = 0x00; // No parity, LSB first, 8-bit data, 1 stop bit, UART, Asynchronous
    UCA0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK source, keep in reset state
    UCA0BR0 = 104; // 9600 Baud rate - Assumes 1 MHz clock
    UCA0BR1 = 0; // 9600 Baud rate - Assumes 1 MHz clock
    UCA0MCTL = 0x02; // 2nd Stage modulation = 1, Oversampling off
    IE2 = 0x00; // Interrupts disabled
    UCA0CTL1 &= ~UCSWRST;*/

    // Analog setup
    ADC10CTL1 = INCH_4 + ADC10DIV_3; // Temperature Sensor and ADC10CLK/4
    // ADC set up parameters
    ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
    __delay_cycles(10000); // required for settling of ADC

    while (1)
    {
    ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start with interrupt
    __bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled, sleep until interrupt
    unsigned long flexADC = ADC10MEM;
    float flexV = flexADC * VCC / 1023;
    float flexR = R_div * (VCC / flexV - 1);

    float angle = map(flexR, straight_resistance, bend_resistance, 0, 90.0);


    // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
    // data shows up magically in ADC10MEM
    serial_string("\tResistance:\t");

    serial_number(flexR);


    serial_string("\tADC:\t");
    serial_number(flexADC);
    // serial_string("\n");

    serial_string("\tAngle:\t");
    serial_number(angle);
    // serial_string("\n");

    }
    }

    // ADC10 interrupt service routine
    #pragma vector=ADC10_VECTOR
    __interrupt void ADC10_ISR(void)
    {
    __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
    }

    //// The following functions allow us to write strings and numbers to our PC through the back channel uart.
    //void serial_charTX(char c)
    //{
    // while (!(IFG2 & UCA0TXIFG))
    // ; // Wait until the transmit buffer is empty
    // UCA0TXBUF = c; // Send the character through the Xmit buffer
    //}
    //
    //char serial_charRX(void)
    //{
    // while (!(IFG2 & UCA0RXIFG))
    // ; // Wait until a character has been received
    // return UCA0RXBUF; // Return received character
    //}
    //
    //void serial_string(char string[])
    //{
    // int i;
    // for (i = 0; string[i] != '\0'; i++) // Send characters until end-of-string
    // {
    // if (string[i] == '\n') // The terminal program recognizes \r as the carriage return
    // serial_charTX('\r');
    // else
    // serial_charTX(string[i]);
    // }
    //}
    //
    //void serial_number(int value)
    //{
    // char string[10];
    //
    // sprintf(string, "%d", value); // Convert an integer to a character string
    //
    // serial_string(string);
    //}

  • Here is serial.h

    /*
    * serial_msp.h
    *
    * Created on: Jun 1, 2012
    * Author: Erioto
    */

    #ifndef SERIAL_MSP_H_
    #define SERIAL_MSP_H_

    #include <msp430g2553.h>
    #include <stdio.h>

    // Function prototypes
    void serial_init(void);
    void serial_charTX(char c);
    char serial_charRX(void);
    void serial_string(char string[]);
    void serial_number(int value);

    #endif /* SERIAL_MSP_H_ */

  • 7142.serial_msp.h

    /*
     * serial_msp.c
     *
     *  Created on: Jun 1, 2012
     *      Author: Erioto
     */
    #include "serial_msp.h"
    
    void serial_init(void)
    {
        P1SEL  = BIT1 + BIT2;				// Select UART as the pin function
        P1SEL2 = BIT1 + BIT2;
    
        UCA0CTL1 |= UCSWRST;				// Disable UART module for configuration
    
    		UCA0CTL0 = 0x00;					// No parity, LSB first, 8-bit data, 1 stop bit, UART, Asynchronous
    		UCA0CTL1 = UCSSEL_2 + UCSWRST;		// SMCLK source, keep in reset state
    	//	UCA0BR0 = 130;						// 9600 Baud rate	- Assumes 16 MHz clock
    	//	UCA0BR1 = 6;						// 9600 Baud rate	- Assumes 16 MHz clock
    		UCA0BR0 = 104;						// 9600 Baud rate	- Assumes 1 MHz clock
        	        UCA0BR1 = 0;						// 9600 Baud rate	- Assumes 1 MHz clock
    		UCA0MCTL = 0x02;					// 2nd Stage modulation = 1, Oversampling off
    		IE2 = 0x00;							// Interrupts disabled
    
    	UCA0CTL1 &= ~UCSWRST;				// Enable UART module
    
    }
    
    void serial_charTX(char c)
    {
        while( !(IFG2 & UCA0TXIFG) );		// Wait until the transmit buffer is empty
        UCA0TXBUF = c;						// Send the character through the Xmit buffer
    }
    
    char serial_charRX(void)
    {
    	while( !(IFG2 & UCA0RXIFG) );		// Wait until a character has been received
    	return UCA0RXBUF;					// Return received character
    }
    
    void serial_string(char string[])
    {
    	int i;
    	for(i = 0; string[i] != '\0'; i++)		// Send characters until end-of-string
    	{
    		if(string[i] == '\n')		// The terminal program recognizes \r as the carriage return
    			serial_charTX('\r');
    		else
    			serial_charTX(string[i]);
    	}
    }
    
    void serial_number(int value)
    {
    	char string[10];
    
    	sprintf(string, "%d", value);		// Convert an integer to a character string
    
    	serial_string(string);
    }
    
    7142.serial_msp.h

  • /*
     * serial_msp.c
     *
     *  Created on: Jun 1, 2012
     *      Author: Erioto
     */
    #include "serial_msp.h"
    
    void serial_init(void)
    {
        P1SEL  = BIT1 + BIT2;				// Select UART as the pin function
        P1SEL2 = BIT1 + BIT2;
    
        UCA0CTL1 |= UCSWRST;				// Disable UART module for configuration
    
    		UCA0CTL0 = 0x00;					// No parity, LSB first, 8-bit data, 1 stop bit, UART, Asynchronous
    		UCA0CTL1 = UCSSEL_2 + UCSWRST;		// SMCLK source, keep in reset state
    	//	UCA0BR0 = 130;						// 9600 Baud rate	- Assumes 16 MHz clock
    	//	UCA0BR1 = 6;						// 9600 Baud rate	- Assumes 16 MHz clock
    		UCA0BR0 = 104;						// 9600 Baud rate	- Assumes 1 MHz clock
        	        UCA0BR1 = 0;						// 9600 Baud rate	- Assumes 1 MHz clock
    		UCA0MCTL = 0x02;					// 2nd Stage modulation = 1, Oversampling off
    		IE2 = 0x00;							// Interrupts disabled
    
    	UCA0CTL1 &= ~UCSWRST;				// Enable UART module
    
    }
    
    void serial_charTX(char c)
    {
        while( !(IFG2 & UCA0TXIFG) );		// Wait until the transmit buffer is empty
        UCA0TXBUF = c;						// Send the character through the Xmit buffer
    }
    
    char serial_charRX(void)
    {
    	while( !(IFG2 & UCA0RXIFG) );		// Wait until a character has been received
    	return UCA0RXBUF;					// Return received character
    }
    
    void serial_string(char string[])
    {
    	int i;
    	for(i = 0; string[i] != '\0'; i++)		// Send characters until end-of-string
    	{
    		if(string[i] == '\n')		// The terminal program recognizes \r as the carriage return
    			serial_charTX('\r');
    		else
    			serial_charTX(string[i]);
    	}
    }
    
    void serial_number(int value)
    {
    	char string[10];
    
    	sprintf(string, "%d", value);		// Convert an integer to a character string
    
    	serial_string(string);
    }
    

  • 1) I don't see where you're setting the AE register.

    2) You've added more code to debug, but without (as near as I can tell) solving the original problem. I suggest you use the debugger to make sure that flexADC, flexV, flexR, and angle are the values you expect. Once you find the discrepancy, you will know where to concentrate. 

**Attention** This is a public forum