Variable runover when not reaching the limit yet - rollover

My variable had a Runover even before it reached its range.
Currently, I am working with timer 2 with a frequency of 90MHz. When I retrieved the current time by __HAL_TIM_GET_COUNTER() and printed it by printf("receive_time: %lu\n", (unsigned long)receive_time), the maximum the receive_time get is 16 bits although I declared it as 32 bits. I observed the printed value and it never exceeded 2^16 -1.
I also tried to print with printf("%" PRIu32 "\n",a); but it also returned the same.
I had another 32-bit variable send_time which is used later to subtract with receive_time. However, it gave me something in the order of 2*10^9 (2147482170 for example) besides some common values.
I want to ask what happen and if I do something wrong. If everything is correct, is there any way to handle the rollover besides having 2 timers starting at different times?
The code is here:
Radio::radio.tx_buf[0] = seq++; /* set payload */
printf("send a ready message\r\n");
Radio::Send(1, 0, 0, 0); /* begin transmission */
send_time = __HAL_TIM_GET_COUNTER(&htim2);
.
.
.
if (Radio::radio.rx_buf[0] == 100)
{
receive_time = __HAL_TIM_GET_COUNTER(&htim2);
printf("receive_time: %lu\n", (unsigned long)receive_time);
printf("send_time: %lu\n", (unsigned long)send_time);
time_difference = (receive_time - send_time)/2;
printf("time_difference: %lu\n", (unsigned long)time_difference);
uint32_t distance = time_difference * 10 / 3;
printf("Distance: %lu\n", (unsigned long)distance);
}```
Thank you in advanced,
Huy Nguyen.

Related

How is the length determined in sendcount and recvcount in MPI.COMM_WORLD.Gather

So after I Bcast the data (clusters[10][5] 2d array) to every other process and then when each one calculates its new local values I want to send them back to the process 0.
But some of the data is missing sometimes (depends on no. of clusters) or the data is not equal to the ones I have in the sending processes.
I don't know why but the max value of recvcount and recvcount need to be divided by size or by some factor, they can't be array size (10 or 10*5 - no. of elements).
If I put its full size for instance cluster.lenght(10) it says indexoutofbounce 19 and if I run with more processes (mpjrun.bat -np 11 name) the higher index occurs in the outofbounce and it always goes up or down by 2 with higher/lower no. of processes (for example I use 5 processes and get outofbounce 9 and then next run use 6 and get 11).
Can someone explain why is Gather's count connected to number of processes or why it can't accept the array size?
And also the program doesn't end after the data is calculated correctly, only if I use 1 process it ends but otherwise it goes out of the loop and then print something to the terminal and after that I have MPI.finalize but nothing happens and I have Ctrl+c to terminate bat job so I can use the terminal again.
The clusterget variable is set to number of clusters*size of proceses so that it stores all the new clusters from other processes so that I can then use them all in the first process so the problem isn't in clusterget variable or maybe is it? Since there isn't really anything documented about sending through a 2d array of floats (yeah I need to use MPI.OBJECT because java doesn't like float if I use float it says Float can't be casted to Float).
MPI.COMM_WORLD.Bcast(clusters, 0, clusters.length, MPI.OBJECT, 0);
//calculate and then send back to 0
MPI.COMM_WORLD.Gather(clusters, 0, clusters.length / size, MPI.OBJECT, clusterget, 0, clusters.length / size, MPI.OBJECT, 0);
if (me == 0) {
for (int j = 0; j < clusters.length; j++) { //adds clusters from each other process to the first ones
for (int i = 0; i < size - 1; i++) {
System.out.println(clusterget[j+i*cluster][4]+" tock "+clusters[j][4]);
clusters[j][2] += clusterget[j + i * cluster][2]; //dodaj
clusters[j][3] += clusterget[j + i * cluster][3];
clusters[j][4] += clusterget[j + i * cluster][4];
}
}
}
In Summmary:
The data from each process isn't the same as the one collected after gather, in which i can't put the full size of 2d float array.
I've changed gather to Send and Recv and it works and I needed to add a Barrier so that the data is in synch before sending. But this only works for 2 procesess.
MPI.COMM_WORLD.Barrier();
if (me != 0){
MPI.COMM_WORLD.Send(clusters,0,clusters.length,MPI.OBJECT,0,MPI.ANY_TAG);
}
if (me == 0) {
for (int i = 1; i < size; i++) {
MPI.COMM_WORLD.Recv(clusterget,0,clusters.length,MPI.OBJECT,i,MPI.ANY_TAG);
for (int j = 0; j < clusters.length; j++) {
clusters[j][2] += clusterget[j][2];
clusters[j][3] += clusterget[j][3];
clusters[j][4] += clusterget[j][4];
}
}

How to control the speed of a stepper motor using PID control and ultrasonic sensor?

Little backstory:
I'm currently doing this project that deals with using two cars, called block A and B, which block B has to maintain a distance of 10 cm from block A using PID, PD, PI, or P. I'm using a PID. Block B uses an Arduino whereas Block A is controlled by the user by hand. Block B uses a unipolar stepper motor as the actuator and an ultrasonic sensor to sense the distance. My professor wants the motor to move in both directions and have varying speeds (slow, medium, and fast). I'm using brett's PID since I have used it before in my previous labs.
Problem:
I have an issue with how to create varying speeds for block B like intuitively I know that I want the B should move for example, fast if the car is greater than 20 cm, medium if the car is between 20cm and 14cm, and slow if it's between 14cm and 10cm. But I just can't use the input value retrieved from the sensor directly to control the motor as it would make it an open system. So I used the error retrieved from Brett's PID code to control the stepper motor. So far, I have gotten the directions to work by setting the myPID.SetOutputLimits(-800,800);. But as it tried to use the error to control the speed it would be impossible because the error always fluctuates at a specific distance. For example at 12cm, I would get either 800 or around 300. I'm currently confused about how to implement control of the speed of my stepper motor through PID and any help regarding this issue will be appreciated.
Code:
Code was through Arduino IDE.
#include "SR04.h"
#include <Stepper.h>
#include <PID_v1.h>
#define TRIG_PIN 7
#define ECHO_PIN 6
//intialization of Ultrasonic sensor
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long s;
//intializing motor variables
int stepsPerRevolution = 2048;
int motorSpeed = 6;
Stepper myStepper (stepsPerRevolution, 8, 10, 9, 11);
//Declared PID variables
double Setpoint = 10; //desired temp value
double Input; //thermsitor
double Output; //DC motor
double Error;
//defined variables for PID parameters
double Kp=100, Ki=10, Kd=1;
//PID equation
PID myPID(&Input, &Output, &Setpoint, Kp, Kd, Ki, REVERSE);
void setup(){
Serial.begin(9600);
//setting PID
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(-800,800);
//speed intialized
myStepper.setSpeed(motorSpeed);
}
void loop(){
s=sr04.Distance();
Input = s;
myPID.Compute();
Error = Input - Setpoint;
//Serial.print(Input);
//Serial.print(",");
//Serial.println(Setpoint);
Serial.println(Output);
//Serial.print(",");
//Serial.println(Error);
Error = Output;
//Away from Block B
if (0<Error<800){
myStepper.setSpeed(motorSpeed);
myStepper.step(-300);
} //slow speed
if (Error>=800){
myStepper.setSpeed(motorSpeed*2);
myStepper.step(-128);
} //fast speed
//Towards Block B
if (-800<Error<0) {
myStepper.setSpeed(motorSpeed);
myStepper.step(128);
} //slow speed
if (Error<=-800) {
myStepper.setSpeed(motorSpeed*2);
myStepper.step(128);
}//Fast speed
}
What you need to do is calcuulate how much you need to change your current speed to minimize the error in distance.
Your calculation for error is not in the right place.
void loop()
{
long s=sr04.Distance();
Input = s; // using global variables to pass values to your PID
// is not a good idea. Use function parameters instead.
// You are storing a 32 bit value in a 16 bit variable!!!
// That's only the start of your problems.
myPID.Compute();
Error = Input - Setpoint; //
Since we're starting with a major design flaw, I'll have to assume you'll fix that and change your PID code to accept and compute long integers both as input value as a function parameter, and as the type of its return value..
What you want to do is compute the PID from the error in distance from your set point, and then modulate the current speed accordingly. PIDs work best when used directly, using 7 speeds (1 stopped, 3 forward/3 backwards) is possible, but I don't think it'll give better results, I'll leave the exercise to you.
I haven't tried this, I don't have any cars on hand. This is a skeletoon of how I'd go about it. Tuning the PID should be what takes you the longest.
//...
// speeds are in RPMs.
long curSpeed = 0;
const long MAX_SPEED = XXX; // whatever you max speed is for your car.
const long MIN_NEG_SPEED = -XXX; // whatever you max speed is for your car going reverse.
const long MIN_SPEED = XXX; // below this absolute speed, we're stopped.
const int SLICE_TIME = 10; // time between readings and adjustments, in ms.
// you'll need to adjust this according to you minimum speed, and steps per turn.
const long STEPS_PER_TURN = 200; // change to whatever you steps/turn value is.
// you'll need to limit the output of your PID to match the acceleration your
// motors can handle for your particular car.
// returns the number of steps to run for our slice time.
long Steps(int speed)
{
if (-MIN_SPEED <= speed && speed <= MIN_SPEED)
return 0;
// compute number of steps for our slice time.
// choose slice time and minimum speed wisely!!
long steps = (SLICE_TIME * (speed * STEPS_PER_TURN)) / (60000L);
// for very low speeds. I've added this, because I'm unsure of the
// time domain behaviour of stepper library with less than 2 steps
if (-1 <= steps && steps <= 1)
{
if (speed < 0)
return -2;
else
return 2;
}
return int(steps);
}
void loop()
{
// You may want to filter the sr04 readings with a median of 5
// filter to limit input noise.
// You want to keep the car at a distance of 'set_point'
// from the leading car. distance_error is the error you want to
// minimize to zero by using the PID, and that's what should be
// the PID input.
//
// The way this works. We are rolling at speed curSpeed, we
// measure the error in distance from our set_point, feed that
// to the PID, then accelerate or decelerate by subtracting
// the output of the PID from the current speed.
//
// Note: you can add or subtract the PID to/from the current speed,
// the sign of the PID depends on you coefficients and sensor.
// I've used subtraction here because that's how you express
// negative feedback mathematically. In real life, we'll use what
// best fits our needs. Usually it's the operation that makes P
// positive.
long distance_error = sr04.Distance() - setPoint;
long pid_out = myPID.Compute(distance_error);
// increment or decrement the current speed to try and reduce the error.
long speed = curSpeed - pid_out; // As usual, PID coefficients do matter
// for this to work well.
if (speed > MAX_SPEED)
speed = MAX_SPEED;
if (speed < MIN_NEG_SPEED)
speed = MIN_NEG_SPEED;
curSpeed = speed;
if (speed < 0)
speed = -speed;
myStepper.setSpeed(speed); // modulate speed
int steps = Steps(curSpeed);
if (steps)
myStepper.step(steps); // keep rolling.
}
I haven't tried to compile it either, so this may not compile as is. But most of the tricks and traps are covered, and this should give you a head start, if you want to go the PID route. But I think your professor will really wonder where that one came from :) Still, you should try and make it run, for fun.
The other way, without a PID, and using set speeds is much more straightforward. It may also be closer to what the is required by the exercise. The distance between cars will vary a bit more, of course. And it does not use a PID at all.
const int MAX_SPEED = 3;
int speed = 0; // value range is [-MAX_SPEED, +MAX_SPEED]
long RPMS[MAX_SPEED + 1] = { 0, 200, 400, 800 }; // in RPMs, assuming average speed will be around 400, in this case.
// For 3 speeds, the difference between speeds cannot be higher than max acceleration.
// You can add as many speeds as desired. More speeds = more precision.
const long STEPS_PER_TURN = 200; // change to whatever you steps/turn value is. MUST be 200 or more.
const int STEPS = STEPS_PER_TURN / 100; // 3.6° between speed adjustment.
// it is very small right now, so
// you will want to play with this value.
// this threshold gives some control over aceleration.
// and 'hardness' of distance tracking.
const long THRESHOLD = 0;
void loop()
{
// get the error in distance.
long distance_error = sr04.Distance() - setPoint;
// modulate speed.
if (distance_error > THRESHOLD)
++speed;
if (distance_error < -THRESHOLD)
--speed;
if (speed > MAX_SPEED)
speed = MAX_SPEED;
if (speed < -MAX_SPEED)
speed = -MAX_SPEED;
long rpm = RPMS[(speed < 0) : -speed : speed];
if (rpm)
{
myStepper.setSpeed(rpm);
myStepper.setSpeed((speed < 0) ? -STEPS : STEPS)
}
}
For this code, you must choose speeds and STEPS value that will give you an acceleration without misssed steps.

Simple low pass filter in fixed point

I have a simple circuit setup to read the light level via an LDR into an Arduino. I'm trying to implement a simple low pass filter to data read in. How best to tackle this given that analogRead() returns an unsigned int.
I have tried to implement a simple fixed point representation but am unsure if this is the correct approach.
Here's a code snippet:
#define WLPF 0.1
#define FIXED_SHIFT 4
ldr_val = ((int)analogRead(A0)) << FIXED_SHIFT;
while (true) {
int newval = (int)analogRead(A0) << FIXED_SHIFT;
ldr_val += WLPF*(newval - ldr_val);
Serial.println(ldr_val >> FIXED_SHIFT, DEC);
}
Note the resolution of the ADC is 10 bits and I am working with an 8-bit Arduino Micro.
I'm paraphrasing from the book "Musical Applications of Microprocessors" by Hal Chamberlin, page 438:
If you allow large numbers in the accumulator, then you can make a first-order low-pass filter with one multiplication and some right-shifts.
out = accum >> k
accum = accum - out + in
Choose 'k' to change the cutoff frequency. The more shifts, the lower the low-pass cutoff, but the larger the value in the accumulator. With a 10-bit value from analog_read(), you can easily right-shift 4 places, and still have 2 bits of headroom in the accumulator (as #datafiddler noted above).
Cypress has some app-notes for their PSOC chips with similar equations, and using shifts. I remember one had a nice table that related number of shifts to the cutoff frequency.
The approximate cutoff frequency is the sampling frequency divided by 2-pi times the gain factor:
f0 ~ fs / (2 pi a)
where 'a' is that power of two.
Keep smoothin' those signals!
On a device with no FPU rather then multiplying by 0.1 (which in any case make this a floating not fixed point implementation) you should divide by 10:
#define WLPF_DIV 10
...
ldr_val += (newval - ldr_val) / WLPF_DIV;
However division on an 8 bit processor is often expensive (although probably dwarfed by the execution time of Serial.println() in the loop - but that is a different issue). Instead it is more efficient to select a power of two so that the division can be performed with a right-shift.
#define WLPF_SHIFT 3 // divide by 8
...
ldr_val += (newval - ldr_val) >> WLPF_SHIFT ;
The use of signed int is problematic since right-shift of a signed type is undefined behaviour. In this case this can be resolved by changing the code to:
#define WLPF_DIV 8
...
ldr_val += (newval - ldr_val) / WLPF_DIV ;
The compiler will most likely spot the power-of-two constant and generate the code using an arithmetic-shift-right in any case. However you would probably do better to reconsider the data type.
You still have a right-shift in the Serial.println() call, but that too could by replaced with a divide-by-16:
#define WLPF_DIV 8
#define FIXED_MUL 16
ldr_val = (int)analogRead(A0) * FIXED_MUL ;
for(;;)
{
int newval = (int)analogRead(A0) * FIXED_MUL ;
ldr_val += (newval - ldr_val) / WLPF_DIV
Serial.println(ldr_val / FIXED_MUL, DEC);
}
Non-deterministic output of the data on a per sample basis is not going to make for a very accurate filter and will dominate the timing in any case so you have little control over the frequency response and it will not be stable. It also makes the previous performance optimisations rather pointless. You may want to think about that if it is important in your application - but that is a different question.
Stick with integer arithmetics:
#define WLPF 9
filtered = ((long)filtered * WLPF + newValue) / (WLPF + 1);

Infra Red Arduino Custom Serial

Basically I am looking to make an serial-like system that runs communication between IR LEDs on an arduino. Below the code gets to the point having an array with a collection of 1s and 0s in it. I need to convert this 8 bit array into a single character and output it. But I don't know how to do this. Help would be appreciated.
int IR_serial_read(){
int output_val;
int current_byte[7];
int counter = 0;
IR_serial_port = digitalRead(4);
if (IR_serial_port == HIGH){
output_val =1;
}
if (IR_serial_port == LOW){
output_val =0;
}
current_byte[counter] = output_val;
counter +=1
}
This would best be done with bitwise operators, I think the or function would be of best use here as it will set a bit if the input is 1 and not change it if it is 0, could use a loop to loop through your array and set the bits.
Looking at your code, are you sure you are receiving all 8 bits? You seem to be saving 7 bits.
As you are creating a byte array solely for the purpose of using only 1s and 0s, it suggest immediately setting the bits in the same loop.
Here is the code that I suggest:
byte inputByte = 0; // Result from IR transfer. Bits are set progressively.
for (byte bit = 0; bit < 8; bit++) { // Read the IR receiver once for each bit in the byte
byte mask = digitalRead(4); // digitalRead returns 1 or 0 for HIGH and LOW
mask <<= bit; // Shift that 1 or 0 into the bit of the byte we are on
inputByte |= mask; // Set the bit of the byte depending on receive
}
This would also be put inside a loop to read all the bytes in your data stream.
It is designed for readability and can be optimised further. It reads the least significant bit first.
You can also apply the same technique to your array if you wish to keep using an array of bytes just for 1s and 0s, just replace the digitalRead with the array location (current_byte[bit]).

MSP430 not able to handle double

I am trying to program a MSP430 with a simple "FIR filter" program, that looks like the following:
#include "msp430x22x4.h"
#include "legacymsp430.h"
#define FILTER_LENGTH 4
#define TimerA_counter_value 12000 // 12000 counts/s -> 12000 counts ~ 1 Hz
int i;
double x[FILTER_LENGTH+1] = {0,0,0,0,0};
double y = 0;
double b[FILTER_LENGTH+1] = {0.0338, 0.2401, 0.4521, 0.2401, 0.0338};
signed char floor_and_convert(double y);
void setup(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_8MHZ; // Set DCO
DCOCTL = CALDCO_8MHZ;
/* Setup Port 3 */
P3SEL |= BIT4 + BIT5; // P3.4,5 = USART0 TXD/RXD
P3DIR |= BIT4; // P3.4 output direction
/* UART */
UCA0CTL1 = UCSSEL_2; // SMCLK
UCA0BR0 = 0x41; // 9600 baud from 8Mhz
UCA0BR1 = 0x3;
UCA0MCTL = UCBRS_2;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
/* Setup TimerA */
BCSCTL3 |= LFXT1S_2; // LFXT1S_2: Mode 2 for LFXT1 = VLO
// VLO provides a typical frequency of 12kHz
TACCTL0 = CCIE; // TACCR0 Capture/compare interrupt enable
TACCR0 = TimerA_counter_value; // Timer A Capture/Compare 0: -> 25 Hz
TACTL = TASSEL_1; // TASSEL_1: Timer A clock source select: 1 - ACLK
TACTL |= MC_1; // Start Timer_A in up mode
__enable_interrupt();
}
void main(void) // Beginning of program
{
setup(); // Call Function setup (see above)
_BIS_SR(LPM3_bits); // Enter LPM0
}
/* USCIA interrupt service routine */
/*#pragma vector=USCIAB0RX_VECTOR;*/
/*__interrupt void USCI0RX_ISR(void)*/
interrupt (USCIAB0RX_VECTOR) USCI0RX_ISR(void)
{
TACTL |= MC_1; // Start Timer_A in up mode
x[0] = (double)((signed char)UCA0RXBUF); // Read received sample and perform type casts
y = 0;
for(i = 0;i <= FILTER_LENGTH;i++) // Run FIR filter for each received sample
{
y += b[i]*x[i];
}
for(i = FILTER_LENGTH-1;i >= 0;i--) // Roll x array in order to hold old sample inputs
{
x[i+1] = x[i];
}
while (!(IFG2&UCA0TXIFG)); // Wait until USART0 TX buffer is ready?
UCA0TXBUF = (signed char) y;
TACTL |= TACLR; // Clear TimerA (prevent interrupt during receive)
}
/* Timer A interrupt service routine */
/*#pragma vector=TIMERA0_VECTOR;*/
/*__interrupt void TimerA_ISR (void)*/
interrupt (TIMERA0_VECTOR) TimerA_ISR(void)
{
for(i = 0;i <= FILTER_LENGTH;i++) // Clear x array if no data has arrived after 1 sec
{
x[i] = 0;
}
TACTL &= ~MC_1; // Stops TimerA
}
The program interacts with a MatLab code, that sends 200 doubles to the MSP, for processing in the FIR filter. My problem is, that the MSP is not able to deal with the doubles.
I am using the MSPGCC to compile the code. When I send a int to the MSP it will respond be sending a int back again.
Your problem looks like it is in the way that the data is being sent to the MSP.
The communications from MATLAB is, according to your code, a sequence of 4 binary byte values that you then take from the serial port and cast it straight to a double. The value coming in will have a range -128 to +127.
If your source data is any other data size then your program will be broken. If your data source is providing binary "double" data then each value may be 4 or 8 bytes long depending upon its internal data representation. Sending one of these values over the serial port will be interpreted by the MSP as a full set of 4 input samples, resulting in absolute garbage for a set of answers.
The really big question is WHY ON EARTH ARE YOU DOING THIS IN FLOATING POINT - on a 16 bit integer processor that (many versions) have integer multiplier hardware.
As Ian said, You're taking an 8bit value (UCA0RXBUF is only 8 bits wide anyway) and expecting to get a 32bit or 64 bit value out of it.
In order to get a proper sample you would need to read UCA0RXBUF multiple times and then concatenate each 8 bit value into 32/64 bits which you then would cast to a double.
Like Ian I would also question the wisdom of doing floating point math in a Low power embedded microcontroller. This type of task is much better suited to a DSP.
At least you should use fixed point math, seewikipedia (even in a DSP you would use fixed point arithmetic).
Hmm. Actually the code is made of my teacher, I'm just trying to make it work on my Mac, and not in AIR :-)
MATLAB code is like this:
function FilterTest(comport)
Fs = 100; % Sampling Frequency
Ts = 1/Fs; % Sampling Periode
L = 200; % Number of samples
N = 4; % Filter order
Fcut = 5; % Cut-off frequency
B = fir1(N,Fcut/(Fs/2)) % Filter coefficients in length N+1 vector B
t = [0:L-1]*Ts; % time array
A_m = 80; % Amplitude of main component
F_m = 5; % Frequency of main component
P_m = 80; % Phase of main component
y_m = A_m*sin(2*pi*F_m*t - P_m*(pi/180));
A_s = 40; % Amplitude of secondary component
F_s = 40; % Frequency of secondary component
P_s = 20; % Phase of secondary component
y_s = A_s*sin(2*pi*F_s*t - P_s*(pi/180));
y = round(y_m + y_s); % sum of main and secondary components (rounded to integers)
y_filt = round(filter(B,1,y)); % filtered data (rounded to integers)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Serial_port_object = serial(comport); % create Serial port object
set(Serial_port_object,'InputBufferSize',L) % set InputBufferSize to length of data
set(Serial_port_object,'OutputBufferSize',L) % set OutputBufferSize to length of data
fopen(Serial_port_object) % open Com Port
fwrite(Serial_port_object,y,'int8'); % send out data
data = fread(Serial_port_object,L,'int8'); % read back data
fclose(Serial_port_object) % close Com Port
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,1,1)
hold off
plot(t,y)
hold on
plot(t,y_filt,'r')
plot(t,y_filt,'ro')
plot(t,data,'k.')
ylabel('Amplitude')
legend('y','y filt (PC)','y filt (PC)','y filt (muP)')
subplot(2,1,2)
hold off
plot(t,data'-y_filt)
hold on
xlabel('time')
ylabel('muP - PC')
figure(1)
It is also not advised to keep interrupt routines doing long processing routines, because you will impact on interrupt latency. Bytes comming from the PC can get easily lost, because of buffer overrun on the serial port.
The best is to build a FIFO buffer holding a resonable number of input values. The USCI routine fills the FIFO while the main program keeps looking for data inside it and process them as they are available.
This way, while the data is being processed, the USCI can interrupt to handle new incomming bytes.
When the FIFO is empty, you can put the main process in a suitable LPM mode to conserve power (and this is the best MSP430 feature). The USCI routine will wake the CPU up when a data is ready (just put the WAKEUP attribute in the USCI handler if you are using MSPGCC).
In such a scenario be sure to declare volatile every variable that are shared between interrupt routines and the main process.

Resources