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/MSP430FR5994: Unable average the data from arduino

Part Number: MSP430FR5994

Tool/software: Code Composer Studio

Hello,

I am using MSP430FR5994 LP. I am receiving data from Arduino every 3 seconds. After every 10 readings I am planning to take an average and store it in the FRAM. After 10 such data in FRAM I am pushing the data through MSP430 CCS serial monitor via UART. I am unable to make my code work. Kindly help me.

Regards,

Prudhvi Sagar

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

#define WRITE_SIZE      10//128
//void FRAMWrite(void);

#pragma PERSISTENT(FRAM_write)
unsigned long FRAM_write[WRITE_SIZE] = {0};

unsigned char count = 0;
volatile unsigned char TXData = 1;
long datanow[10] = {0};
long data;
int d = 0;
int k = 0;
long avge = 0;
//******************************************************************************
// Pin Config ******************************************************************
//******************************************************************************

#define LED_OUT     P1OUT
#define LED_DIR     P1DIR
#define LED0_PIN    BIT0
#define LED1_PIN    BIT1


//******************************************************************************
// UART Initialization *********************************************************
//******************************************************************************

#define SMCLK_115200     0
#define SMCLK_9600      1
#define ACLK_9600       2

#define UART_MODE       SMCLK_9600

void initUART()
{
    // Configure USCI_A3 for UART mode
    UCA0CTLW0 = UCSWRST;                      // Put eUSCI in reset

#if UART_MODE == SMCLK_115200

    UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK

    // Baud Rate Setting
    // Use Table 30-5 in Family User Guide
    UCA0BR0 = 8;
    UCA0BR1 = 0;
    UCA0MCTLW |= UCOS16 | UCBRF_10 | 0xF700;   //0xF700 is UCBRSx = 0xF7

#elif UART_MODE == SMCLK_9600

    UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK

    // Baud Rate Setting
    // Use Table 30-5 in Family User Guide
    UCA0BR0 = 104;
    UCA0BR1 = 0;
    UCA0MCTLW |= UCOS16 | UCBRF_2 | 0xD600;   //0xD600 is UCBRSx = 0xD6

#elif UART_MODE == ACLK_9600

    UCA0CTLW0 |= UCSSEL__ACLK;               // CLK = ACLK
    // Baud Rate calculation
    // 32768/(9600) = 3.4133
    // Fractional portion = 0.4133
    // Use Table 24-5 in Family User Guide
    UCA0BR0 = 3;                             // 32768/9600
    UCA0BR1 = 0;
    UCA0MCTLW |= 0x9200;    //0x9200 is UCBRSx = 0x92

#else
    # error "Please specify baud rate to 115200 or 9600"
#endif

    UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
    UCA0IE |= UCRXIE;                         // Enable USCI_A3 RX interrupt

    // Configure USCI_A3 for UART mode
        UCA3CTLW0 = UCSWRST;                      // Put eUSCI in reset

    #if UART_MODE == SMCLK_115200

        UCA3CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK

        // Baud Rate Setting
        // Use Table 30-5 in Family User Guide
        UCA3BR0 = 8;
        UCA3BR1 = 0;
        UCA3MCTLW |= UCOS16 | UCBRF_10 | 0xF700;   //0xF700 is UCBRSx = 0xF7

    #elif UART_MODE == SMCLK_9600

        UCA3CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK

        // Baud Rate Setting
        // Use Table 30-5 in Family User Guide
        UCA3BR0 = 104;
        UCA3BR1 = 0;
        UCA3MCTLW |= UCOS16 | UCBRF_2 | 0xD600;   //0xD600 is UCBRSx = 0xD6

    #elif UART_MODE == ACLK_9600

        UCA3CTLW0 |= UCSSEL__ACLK;               // CLK = ACLK
        // Baud Rate calculation
        // 32768/(9600) = 3.4133
        // Fractional portion = 0.4133
        // Use Table 24-5 in Family User Guide
        UCA3BR0 = 3;                             // 32768/9600
        UCA3BR1 = 0;
        UCA3MCTLW |= 0x9200;    //0x9200 is UCBRSx = 0x92

    #else
        # error "Please specify baud rate to 115200 or 9600"
    #endif

        UCA3CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
        UCA3IE |= UCRXIE;                         // Enable USCI_A3 RX interrupt
}

//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************

void initGPIO()
{
    //LEDs
    LED_DIR |= LED0_PIN | LED1_PIN;
    LED_OUT &= ~(LED0_PIN | LED1_PIN);         // turn off LEDs

    // Configure UART
   // P2SEL1 &= ~(BIT0 | BIT1);                 //0 USCI_A3 UART operation
   // P2SEL0 |= BIT0 | BIT1;

    P2SEL1 |= BIT0 | BIT1;                 //1 USCI_A0 UART operation
    P2SEL0 &= ~(BIT0 | BIT1);                      //0

    // Configure UART
      P6SEL1 &= ~(BIT0 | BIT1);                 // USCI_A3 UART operation
      P6SEL0 |= BIT0 | BIT1;

    // Configure PJ.5 PJ.4 for external crystal oscillator
    PJSEL0 |= BIT4 | BIT5;                    // For XT1

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
}

void sensor_reading(long data)
{
    int c = 0;
    int t = 0;

    datanow[d] = data;

    //First 10 data are averaged.....then stored in FRAM......When FRAM reaches 10 sends back received data (HAS TO SEND ALL DATA)
    if(d == 9)          //Enters only after 10 UART messages
    {
        for(c = 0; c < 10 ; c++)
            {
             avge = avge + datanow[c];
             if(c == 9)             //enters every 10 UART message
                 {avge = (avge/10);
                  P1OUT ^= BIT0;        //Check
                  FRAM_write[k] = avge;
                  k++;                  //Adds upto one every 10 messages
                  if(k == 9)
                  {
                      for (t = 0; t < 9; t++)
                                 {
                                     P1OUT ^= BIT0;
                                     UCA0TXBUF = FRAM_write[t];    //giving data for single digit numbers....if want for full nuber should do for every digit
                                     __delay_cycles(1400);
                                 }
                      k = 0;
                  }
                  avge = 0;
                  }
            }
        d = 0;
    }

}
void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    // Clock System Setup
    CSCTL0_H = CSKEY_H;                     // Unlock CS registers
    CSCTL1 = DCOFSEL_0;                     // Set DCO to 1MHz
    // Set SMCLK = MCLK = DCO, ACLK = LFXTCLK (VLOCLK if unavailable)
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
    // Per Device Errata set divider to 4 before changing frequency to
    // prevent out of spec operation from overshoot transient
    CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4;   // Set all corresponding clk sources to divide by 4 for errata
    CSCTL1 = DCOFSEL_4 | DCORSEL;           // Set DCO to 16MHz
    // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
    __delay_cycles(60);
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;   // Set all dividers to 1 for 16MHz operation

    CSCTL4 &= ~LFXTOFF;
    do
    {
    CSCTL5 &= ~LFXTOFFG;                      // Clear XT1 fault flag
    SFRIFG1 &= ~OFIFG;
    }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

    CSCTL0_H = 0;                             // Lock CS registerss
}

//******************************************************************************
// Main ************************************************************************
// Enters LPM0 if SMCLK is used and waits for UART interrupts. If ACLK is used *
// then the device will enter LPM3 mode instead. The UART RX interrupt handles *
// the received character and echoes it.                                       *
//******************************************************************************

int main(void)
{
  WDTCTL = WDTPW | WDTHOLD;                 // Stop Watchdog
  //int d = 0;
  initGPIO();
  initClockTo16MHz();
  initUART();
  P1OUT &= ~BIT0;                         // Clear P1.0 output latch for a defined power-on state
  P1DIR |= BIT0;
  printf("Hello World");// Set P1.0 to output direction
  //UCA0TXBUF = '7';
//  while(!(UCA0IFG & UCTXIFG));
//         UCA0TXBUF = TXData;                 // Load data onto buffer

#if UART_MODE == ACLK_9600
    __bis_SR_register(LPM3_bits + GIE);       // Since ACLK is source, enter LPM3, interrupts enabled
#else
    __bis_SR_register(LPM0_bits + GIE);       // Since SMCLK is source, enter LPM0, interrupts enabled
#endif
  __no_operation();                         // For debugger
}

//******************************************************************************
// UART Interrupt ***********************************************************
//******************************************************************************

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A3_VECTOR
__interrupt void USCI_A3_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A3_VECTOR))) USCI_A3_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCA3IV, USCI_UART_UCTXCPTIFG))
  {
    case USCI_NONE: break;
    case USCI_UART_UCRXIFG:
      while(!(UCA3IFG&UCTXIFG));
      UCA0TXBUF = UCA3RXBUF;
      sensor_reading(UCA3RXBUF);
      d++;                              //Counter for UART data
     __no_operation();
      break;
    case USCI_UART_UCTXIFG: break;
    case USCI_UART_UCSTTIFG: break;
    case USCI_UART_UCTXCPTIFG: break;
  }
}

  • Hi Prudhvi,

    Can you please provide some more details about what is not functioning correctly? Have you done some debugging that you could share as well? Thanks!
  • Hello,

    I am turning ON an LED when it sends data from FRAM. This has to be done every 100 received numbers, but here it happens in every 20 times. It doesnt send the full 10 numbers I need, it just sends a random character.

    Regards,

    Prudhvi Sagar

  • > it just sends a random character
    Are you trying to view these bytes in ASCII? If so, they probably won't display well.
    ---------------------------------------
    > I am turning ON an LED when it sends data from FRAM.
    It actually is toggling the LED. If I've counted correctly, it will be on during input samples 11-20, 31-40, and so on. Is that what you're seeing?
    ---------------------------------------
    > UCA0TXBUF = FRAM_write[t]; //giving data for single digit numbers....if want for full nuber should do for every digit
    > __delay_cycles(1400);
    If your clock is really 16MHz, this isn't nearly long enough to wait for the byte to be sent. Sending a byte at 9600bps takes about 1ms, or 16MHz/1000=16000 cycles. Putting data into TXBUF before it's ready will lose the data. The usual way to wait is to spin on UCTXIFG (as seen in the ISR).

    Doing this in the ISR will lock out the Rx side (and drop any incoming data) for at least 10ms. How fast is the data coming from the Arduino?
    ---------------------------------------
    > while(!(UCA3IFG&UCTXIFG));
    > UCA0TXBUF = UCA3RXBUF;
    This is echoing whatever you get on UCA3 (Arduino data) to UCA0 (results). Is this intentional? I seems it would just muddy your data stream, but that's up to you. (You should be spinning on UCA0IFG, not UCA3IFG.)
  • ---------------------------------------
    > while(!(UCA3IFG&UCTXIFG));
    > UCA0TXBUF = UCA3RXBUF;
    This is echoing whatever you get on UCA3 (Arduino data) to UCA0 (results). Is this intentional? I seems it would just muddy your data stream, but that's up to you. (You should be spinning on UCA0IFG, not UCA3IFG.)
    >>>>>>>Yes it is intentional.....I dont get good echo of the bytes being sent by Arduino, I get ASCII values...I get good echo if i send keystrokes using usb to TTL converter too instead of Arduino connected there.

    ----------------------------------------
    > it just sends a random character
    Are you trying to view these bytes in ASCII? If so, they probably won't display well.
    >>>>>So the issue is only displaying? Is my averaging correct?

    ---------------------------------------
    > I am turning ON an LED when it sends data from FRAM.
    It actually is toggling the LED. If I've counted correctly, it will be on during input samples 11-20, 31-40, and so on. Is that what you're seeing?
    >>>>>>>After every 20 numbers sent by Arduino LED gets toggled. Why is this happening? Shouldnt this happen after every 100 data points sent by Arduino.

    ----------------------------------------
    > UCA0TXBUF = FRAM_write[t]; //giving data for single digit numbers....if want for full nuber should do for every digit
    > __delay_cycles(1400);
    If your clock is really 16MHz, this isn't nearly long enough to wait for the byte to be sent. Sending a byte at 9600bps takes about 1ms, or 16MHz/1000=16000 cycles. Putting data into TXBUF before it's ready will lose the data. The usual way to wait is to spin on UCTXIFG (as seen in the ISR).

    Doing this in the ISR will lock out the Rx side (and drop any incoming data) for at least 10ms. How fast is the data coming from the Arduino?
    >>>>>>>I have added this as you have suggested "while(!(UCA0IFG&UCTXIFG));" --- works smoothly.
    ----------------------------------------


  • ---------------------------------------
    > I am turning ON an LED when it sends data from FRAM.
    It actually is toggling the LED. If I've counted correctly, it will be on during input samples 11-20, 31-40, and so on. Is that what you're seeing?
    >>>>>>>After every 20 numbers sent by Arduino LED gets toggled. Why is this happening? Shouldnt this happen after every 100 data points sent by Arduino.

    $$$$$$$$$ I made a mistake by adding another check which was unintended........When I place a check inside FRAM loop and another check for every 10 data received from Arduino.... they toggle perfectly. The data I receive from FRAM is not understandable but do you think thats only the issue of representing but the averaging going inside is fine? Is there anyway I can check it, sadly my printf doesnt work :(.

    I have now sent the data to Arduino (instead of CCS serial) and checked its serial monitor....everything seems to work fine...Thank you for support

**Attention** This is a public forum