Dhruvi narielwalaMahshid Mansouri
Published

Ball Beam Balance

The goal for this project is to control the position of a ball on a beam that is actuated by a motor while using 5 LED lights as indicator.

IntermediateShowcase (no instructions)1,376
Ball Beam Balance

Things used in this project

Hardware components

MSP430 Microcontroller
Texas Instruments MSP430 Microcontroller
×1
myRIO
×1
DC motor
×1
Webcam, Logitech® HD Pro
Webcam, Logitech® HD Pro
×1
motor amplifier
×1
Makerbeam
Makerbeam
×1

Software apps and online services

LabVIEW Community Edition
LabVIEW Community Edition
Code Composer Studio
Texas Instruments Code Composer Studio

Story

Read more

Code

The code for I2C serial communication between the MSP430 and myRIO in Code Composer Studio software

C/C++
This file includes the code we've developed for the I2C serial communication between the MSP430 and myRIO. In this code, the real-time position data of the ball on the beam from the camera in LabVIEW, has been sent to the MSP430 using I2C protocol. Then, by using the data received from myRIO, five different LEDs turn on and off depending on the position of the ball on the beam. The I2C as well as the digital I/O registers configuration codes for turning on an off the LEDs have been included in the code.
/******************************************************************************
University of Illinois at Urbana Champaign
ME461 Final Project/Fall 2019/Ball and Beam Balance System
Mahshid Mansouri and Dhruvi Narielwala 

MSP430F2272 Project Creator 4.0
ME 461 - S. R. Platt
Fall 2010
Updated for CCSv4.2 Rick Rekoske 8/10/2011
Written by: Steve Keres
College of Engineering Control Systems Lab
University of Illinois at Urbana-Champaign
 *******************************************************************************/

#include "msp430x22x2.h"
#include "UART.h"

char newprint = 0;
unsigned long timecnt = 0;
unsigned char RXData[8]={0,0,0,0,0,0,0,0};
unsigned char TXData[8]={0,0,0,0,0,0,0,0};
int count = 0;
int count1 = 0;
long rxlong1 = 0;
long rxlong2 = 0;
long byte1 = 123;
long byte2 = 456;
void main(void) {

    WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

    if (CALBC1_16MHZ ==0xFF || CALDCO_16MHZ == 0xFF) while(1);

    DCOCTL = CALDCO_16MHZ;                      // Set uC to run at approximately 16 Mhz
    BCSCTL1 = CALBC1_16MHZ;

    //P1IN              Port 1 register used to read Port 1 pins setup as Inputs
    P1SEL &= ~0xFF; // Set all Port 1 pins to Port I/O function
    P1REN &= ~0xFF; // Disable internal resistor for all Port 1 pins
    P1DIR |= 0xFF;  // Set Port 1 Pin 0 and Pin 1 (P1.0,P1.1) as an output.  Leaves Port1 pin 2 through 7 unchanged
    P1OUT &= ~0xFF;  // Initially set all Port 1 pins set as Outputs to zero
    P1IFG &= ~0xFF;  // Clear Port 1 interrupt flags
    P1IES &= ~0xFF; // If port interrupts are enabled a High to Low transition on a Port pin will cause an interrupt
    P1IE &= ~0xFF; // Disable all port interrupts

    //Add your code here to initialize USCIB0 as an I2C slave

    // Timer A Config
    TACCTL0 = CCIE;                           // Enable Timer A interrupt
    TACCR0 = 16000;                           // period = 1ms
    TACTL = TASSEL_2 + MC_1;                  // source SMCLK, up mode

    /* Uncomment this block when using the wireless modems on the robots
    // Wireless modem control pins
    P2SEL &= ~0xC0; // Digital I/O
    P2REN &= ~0xC0; // Disable internal resistor for P2.6 and P2.7
    P2OUT |= 0x80;          // CMD/Data pin high for data
    P2DIR |= 0x80;          // Output direction for CMD/data pin (P2.7)
    P2DIR &= ~0x40;         // Input direction for CTS pin (P2.6)
    P1IFG &= ~0xC0;  // Clear Port P2.6 and P2.7 interrupt flags
    P1IES &= ~0xC0; // If port interrupts are enabled a High to Low transition on a Port pin will cause an interrupt
    P1IE &= ~0xC0; // Disable P2.6 and P2.7 interrupts
     */

    //P3IN              Port 1 register used to read Port 1 pins setup as Inputs
    P3SEL |=0x06; // Set all Port 1 pins to Port I/O function
    //      P1REN &= ~0xFF; // Disable internal resistor for all Port 1 pins
    //      P1DIR |= 0x3;  // Set Port 1 Pin 0 and Pin 1 (P1.0,P1.1) as an output.  Leaves Port1 pin 2 through 7 unchanged
    // I2C configuration
    UCB0CTL1=UCSWRST+UCSSEL_3;
    UCB0CTL0=UCSYNC+UCMODE_3;
    UCB0I2COA=0x25;
    UCB0CTL1&=~UCSWRST;
    IE2|=UCB0RXIE;
    IFG2&= ~UCB0RXIFG;
    Init_UART(115200,1);  // Initialize UART for 9600 baud serial communication

    _BIS_SR(GIE);   // Enable global interrupt


    while(1) {

        if(newmsg) {
            //my_scanf(rxbuff,&var1,&var2,&var3,&var4);
            newmsg = 0;
        }

        if (newprint)  {
            //P1OUT ^= 0x1;     // Blink LED
            UART_printf("%d\n\r",(int)(RXData[1]));
            //            UART_printf("T:TXData\n\r", TXData);
            // UART_send(1,(float)timecnt/500);
            newprint = 0;
        }

    }
}


// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
    timecnt++; // Keep track of time for main while loop.

    if ((timecnt%500) == 0) {
        //        newprint = 1;  // flag main while loop that .5 seconds have gone by.
    }

}


/*
// ADC 10 ISR - Called when a sequence of conversions (A7-A0) have completed
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void) {
}
 */


// USCI Transmit ISR - Called when TXBUF is empty (ready to accept another character)
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void) {

    if((IFG2&UCA0TXIFG) && (IE2&UCA0TXIE)) {        // USCI_A0 requested TX interrupt
        if(printf_flag) {
            if (currentindex == txcount) {
                senddone = 1;
                printf_flag = 0;
                IFG2 &= ~UCA0TXIFG;
            } else {
                UCA0TXBUF = printbuff[currentindex];
                currentindex++;
            }
        } else if(UART_flag) {
            if(!donesending) {
                UCA0TXBUF = txbuff[txindex];
                if(txbuff[txindex] == 255) {
                    donesending = 1;
                    txindex = 0;
                } else {
                    txindex++;
                }
            }
        }

        IFG2 &= ~UCA0TXIFG;
    }

    if((IFG2&UCB0RXIFG) && (IE2&UCB0RXIE)) {    // USCI_B0 RX interrupt occurs here for I2C
        // put your RX code here.
        RXData[count]=UCB0RXBUF;
        count++;
        if(count==1){
            if((25<=(int)(RXData[1])) && ((int)(RXData[1])<=47)){
                P1OUT&=~0xFF;
                P1OUT|=0x01;
                //P1OUT&=~0x01;
            }
            else if((20<=(int)(RXData[1])) && ((int)(RXData[1])<=47)){
                P1OUT&=~0xFF;
                P1OUT|=0x02;
            }
            else if((0<=(int)(RXData[1])) && ((int)(RXData[1])<=20)){
                P1OUT&=~0xFF;
                P1OUT|=0x04;
            }
            else if((240<=(int)(RXData[1])) && ((int)(RXData[1])<=255)){
                P1OUT&=~0xFF;
                P1OUT|=0x08;
            }
            else if((220<=(int)(RXData[1])) && ((int)(RXData[1])<=240)){
                P1OUT&=~0xFF;
                P1OUT|=0x10;
            }
        }
        if (count>7) {
            count=0;
            TXData[0]=(unsigned char)(byte1>>24);
            TXData[1]=(unsigned char)(byte1>>16);
            TXData[2]=(unsigned char)(byte1>>8);
            TXData[3]=(unsigned char)(byte1);
            TXData[4]=(unsigned char)(byte2>>24);
            TXData[5]=(unsigned char)(byte2>>16);
            TXData[6]=(unsigned char)(byte2>>8);
            TXData[7]=(unsigned char)(byte2);
            newprint=1;
            IE2&=~UCB0RXIE;
            IE2|=UCB0TXIE;

        }
        IFG2 &= ~UCB0RXIFG;
    } else if ((IFG2&UCB0TXIFG) && (IE2&UCB0TXIE)) { // USCI_B0 TX interrupt
        // put your TX code here.
        UCB0TXBUF=TXData[count1];
        count1++;
        if (count1>7) {
            count1=0;
            //P1OUT|=0x02;
            IE2&=~UCB0TXIE;
            IE2|=UCB0RXIE;
        }
        IFG2 &= ~UCB0TXIFG;
    }

}


// USCI Receive ISR - Called when shift register has been transferred to RXBUF
// Indicates completion of TX/RX operation
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void) {

    if((IFG2&UCA0RXIFG) && (IE2&UCA0RXIE)) {  // USCI_A0 requested RX interrupt (UCA0RXBUF is full)

        if(!started) {  // Haven't started a message yet
            if(UCA0RXBUF == 253) {
                started = 1;
                newmsg = 0;
            }
        } else {    // In process of receiving a message
            if((UCA0RXBUF != 255) && (msgindex < (MAX_NUM_FLOATS*5))) {
                rxbuff[msgindex] = UCA0RXBUF;

                msgindex++;
            } else {    // Stop char received or too much data received
                if(UCA0RXBUF == 255) {  // Message completed
                    newmsg = 1;
                    rxbuff[msgindex] = 255; // "Null"-terminate the array
                }
                started = 0;
                msgindex = 0;
            }
        }
        IFG2 &= ~UCA0RXIFG;
    }

    if((UCB0I2CIE&UCNACKIE) && (UCB0STAT&UCNACKIFG)) { // I2C NACK interrupt

        UCB0STAT &= ~UCNACKIFG;
    }
    if((UCB0I2CIE&UCSTPIE) && (UCB0STAT&UCSTPIFG)) { // I2C Stop interrupt

        UCB0STAT &= ~UCSTPIFG;
    }
    if((UCB0I2CIE&UCSTTIE) && (UCB0STAT&UCSTTIFG)) { //  I2C Start interrupt

        UCB0STAT &= ~UCSTTIFG;
    }
    if((UCB0I2CIE&UCALIE) && (UCB0STAT&UCALIFG)) {  // I2C Arbitration Lost interrupt

        UCB0STAT &= ~UCALIFG;
    }
}

LabVIEW Code for the ball and beam balance system

C#
No preview (download only).

Credits

Dhruvi narielwala

Dhruvi narielwala

1 project • 1 follower
Mahshid Mansouri

Mahshid Mansouri

1 project • 1 follower
Thanks to Daniel J.Block.

Comments