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.

MSP430G2231 Want to increase sampling speed

Other Parts Discussed in Thread: MSP430G2231, MSP430G2553

Hello all,

I am very new to Micro controller programming. I am using the MSP430G2231 with launchpad. My objective is to sample sound signal and send the analog to digital value to computer where it has to saved in text file. I am communicating through USB port, and using p1.7 as the input channel for the sound signal. I have written the following code,

For MSP430G2231:

/*
 * main.c
 */
#include  "msp430g2231.h"

#define     LED0                  BIT0
#define     LED1                  BIT6
#define     TXD                   BIT1         // TXD on P1.1

//   Conditions for 9600/4=2400 Baud SW UART, SMCLK = 1MHz
#define     Bitime_5              20       // ~ 0.5 bit length + small adjustment
#define     Bitime                52

int value=0;
unsigned char BitCnt;      //Bit Counter
int  TXByte;      //Data to send

void ConfigureTimerUart(void);
void Transmit(void);

void ConfigureAdc(void)
{
  /* Configure ADC  Channel */
  ADC10CTL1 = INCH_7 + ADC10DIV_3 ;         // Channel 7, ADC10CLK/4
  ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE;  //Vcc & Vss as reference
  ADC10AE0 |= BIT7;                         //P1.7 ADC option
}

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  BCSCTL1 = CALBC1_1MHZ;                    // Set range
  DCOCTL = CALDCO_1MHZ;
  BCSCTL2 &= ~(DIVS_3);                  // SMCLK = DCO = 1MHz
  P1OUT &= ~(LED0 + LED1);
  P1SEL |= TXD;                             // Select I/O pins for UART
  P1DIR |= TXD;


  ConfigureAdc();
  __enable_interrupt();
  while(1)
    {
     //__delay_cycles(1000);                   // Wait for ADC Ref to settle
      ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
      __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled
      value = ADC10MEM;
      if(value>255)
      {
          //flag sent
          int n = value/255;
          ConfigureTimerUart();
          TXByte = n+1;
          Transmit();
          //Break it into multiple bytes
          while(value > 0)
          {
            int x = value - 255;
            if(x < 0)
            {
                ConfigureTimerUart();
                TXByte = value;
                Transmit();
            }
            else
            {
                ConfigureTimerUart();
                TXByte = 255;
                Transmit();
            }
                value = x;
          }
      }
      else
      {
          ConfigureTimerUart();
          TXByte = value;
          Transmit();
      }

    }

  }

void ConfigureTimerUart(void)
{
    CCTL0 = OUT;                               // TXD Idle as Mark
    TACTL = TASSEL_2 + MC_2 + ID_3;            // SMCLK/8, continuous mode
}

// Function Transmits Character from TXByte
void Transmit()
{
 
  while (CCR0 != TAR)                       // Prevent async capture
    CCR0 = TAR;                             // Current state of TA counter
  CCR0 += Bitime;                          // Some time till first bit
  TXByte |= 0x100;                          // Add mark stop bit to TXByte
  TXByte = TXByte << 1;               // Add space start bit
  CCTL0 =  CCIS0 + OUTMOD0 + CCIE;          // TXD = mark = idle
  while ( CCTL0 & CCIE );               // Wait for TX completion
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
    static unsigned char txBitCnt = 10;
    CCR0 += Bitime;                           // Add Offset to CCR0
    if (CCTL0 & CCIS0)                    // TX on CCI0B?
    {
      if ( txBitCnt == 0)
      {
        CCTL0 &= ~ CCIE;
        txBitCnt = 10;
        // All bits TXed, disable interrupt
      }
      else
      {
        CCTL0 |=  OUTMOD2;                    // TX Space
        if (TXByte & 0x01)
        CCTL0 &= ~ OUTMOD2;               // TX Mark
        TXByte = TXByte >> 1;
        txBitCnt --;
      }
    }
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Return to active mode
}

And for the front end in java :

package javaapplication3;

import gnu.io.*;
import java.io.*;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.TooManyListenersException;

public class SimpleRead implements Runnable, SerialPortEventListener {
    static CommPortIdentifier portId;
    static Enumeration portList;

InputStream inputStream;
SerialPort serialPort;
Thread readThread;
byte[] readBuffer;
int count=0;
public static void main(String[] args) {
    portList = CommPortIdentifier.getPortIdentifiers();
    System.out.println("portList... " + portList);
    while (portList.hasMoreElements()) {
        portId = (CommPortIdentifier) portList.nextElement();
        if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
            System.out.println("port identified is Serial.. "
                    + portId.getPortType());
            if (portId.getName().equals("COM9")) {
                System.out.println("port identified is COM9.. "
                        + portId.getName());
                // if (portId.getName().equals("/dev/term/a")) {
                SimpleRead reader = new SimpleRead();
            } else {
                System.out.println("unable to open port");
            }
        }
    }
}

public SimpleRead() {
    try {
        System.out.println("In SimpleRead() contructor");
        serialPort = (SerialPort) portId.open("SimpleReadApp",2400);
        System.out.println(" Serial Port.. " + serialPort);
    } catch (Exception e) {
        System.out.println("Port in use Exception");
    }
    try {
        inputStream = serialPort.getInputStream();
        System.out.println(" Input Stream... " + inputStream);
    } catch (IOException e) {
        System.out.println("IO Exception");
    }
    try {
        serialPort.addEventListener(this);

    } catch (TooManyListenersException e) {
        System.out.println("Tooo many Listener exception");
    }
    serialPort.notifyOnDataAvailable(true);
    try {

        serialPort.setSerialPortParams(2400, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1, SerialPort.PARITY_MARK);

        // no handshaking or other flow control
        serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);


        System.out.println("................");

    } catch (UnsupportedCommOperationException e) {
        System.out.println("UnSupported comm operation");
    }
    readThread = new Thread(this);
    readThread.start();
}

public void run() {
    try {
        System.out.println("In run() function ");
        Thread.sleep(1);
    } catch (InterruptedException e) {
        System.out.println("Interrupted Exception in run() method");
    }
}

public void serialEvent(SerialPortEvent event) {

    switch (event.getEventType()) {
     case SerialPortEvent.DATA_AVAILABLE:
        readBuffer = new byte[8];

        try {
                while (inputStream.available()>0) {
                count++;
                System.out.println("Count = " + count);
            double numBytes = inputStream.read();
            if(numBytes == 2)
            {
                double numBytes1 = inputStream.read();
                double numBytes2 = inputStream.read();
                numBytes = numBytes2 + numBytes1;
            }
            if(numBytes == 3)
            {
                double numBytes1 = inputStream.read();
                double numBytes2 = inputStream.read();
                double numBytes3 = inputStream.read();
                numBytes = numBytes2 + numBytes1 + numBytes3;
            }
            numBytes = numBytes * 3.48;
            DecimalFormat df = new DecimalFormat("#.##");
            String output = df.format(numBytes);

            FileWriter fwo = new FileWriter( "d:\\test.txt", true );
            BufferedWriter bwObj = new BufferedWriter( fwo );
            bwObj.write( output );
            bwObj.newLine( );
            bwObj.close( );

            System.out.println(output);
            }


            

        } catch (IOException e) {
            System.out.println("IO Exception in SerialEvent()");
        }
        break;
    }
   
}

}

The code work fine, but the sampling rate is too slow. I need to sample at the maximum speed to increase accuracy since it is a sound signal. Please suggest me ways to increase the sampling speed at the maximum rate.

Thank you..

  • I think the 2400 b/s software UART is a bottle-neck. You can use 9600 b/s with the existing Application COM Port.

    But to do that, you need to speed up the DCO clock. One way is to solder the 32768 Hz that came with the LaunghPad. Use that as a reference to turn-up DCO. Another way is to calibrate the DCO at a higher rate. 

  • BTW even 9600 b/s is still too slow. You may need to do some sort of DSP on the raw ADC result before you send it so that the data is more compact.

  • Thanks old_cow_yellow for your reply. After I solder the 32k crystal to the board can you pls explain what changes I need to do to the code I posted. I was trying to change the BCSCTL1 to CALBC1_16MHZ and  DCOCTL to CALDCO_16MHZ but CCS gives an error. Please help me out with it..

  • I saw ADC10 in MSP430G2231 launchpad user guide that it includes greater than 200-ksps maximum conversion rate and a maximum baud rate of 9600. My requirement is to get at least 20000 samples per second. So If I use 9600 baud rate will I achieve my requirement ?

  • There is no problem to get 20000 samples per second. But if you send those samples out with an UART at 9600 baud rate, it will take at lease 21 seconds.

    To put it in another way. If you use 9600 baud rate, you can send out at most 960 samples per second.

    That is why I said you need some DSP to compress the raw data before you send them out.

  • Ya I got your point. Will work on the DSP part.

    As for now can you please guide me what changes I have to make to get the 9600 baud rate in my program and how to calibrate the DCO after attaching the 32k crystal. 

  • Dr. Joyanta Kumar Roy said:
    Ya I got your point. Will work on the DSP part.

    I don't think this will get you much further.

    9600Bd means you have a bandwidth of (9600/10)*8=7680 bit per second. For 20k samples per second, this gives you a whopping 0.384 bit per sample. Unless your samples are very, very, very good compressable, no DSP will crunch the data that far.

    You simply can't put 100 people onto a bike, no matter how much you squeeze them. You'll need a bus.

    What could work is if you don't need the samples itself btu a derived information. e.g. if you sample an input and the information you need it exactly when it changes. Then you'll take 20k sampels to find the exact moment of signal change, but the information you need to pass is a simple and short time information.

  • Thanks Jens-Micheal, you gave a very good suggestion. I will be analyzing Heart Beat Signal. I will implement it experimentally soon, still if this method also fails can you suggest any other way to reach my objective ?

    The launchpad has a limitation of 9600 baud rate. So without using the launchpad can we design some UART which can operate at greater Baud rate?

  • The USCI hardware UART in the G2553 and many other MSPs supports up to 1MBd, which is 100kB/s. It is just the ser->USB converter that it limited to 9600Bd because its main data capacity goes to the FET for JTAG programming and debugging.
    You can pull the RX and TX jumper onteh LaunchPad and connect the two lines to e.g. an FTDI USB_ser converter with TTL (3.3V) output and the MSP430G2553 can do up to 1MBd. Well, then you won't need the LaunchPad anymore except for programming and debugging :)

**Attention** This is a public forum