/******************************************************************************
MSP430G2553 Project Creator
GE 423 - Dan Block
Spring(2012)
Written(by) : Steve(Keres)
College of Engineering Control Systems Lab
University of Illinois at Urbana-Champaign
*******************************************************************************/
#include "msp430g2553.h"
#include "UART.h"
char newprint = 0;
unsigned long timecnt = 0;
unsigned int ADC[4]={0,0,0,0}; // Array to hold ADC values (A0 A1 A2 A3)
int A0value = 0;
int A3value = 0;
char newADC = 0;
int statevar = 2;
int timecount = 0;
int spraycount = 0;
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;
// Initialize Port 1 IR Readings as ADC MEM Input
P1SEL &= ~0x09; // See page 42 and 43 of the G2553's datasheet, It shows that when both P1SEL and P1SEL2 bits are zero
P1SEL2 &= ~0x09; // the corresponding pin is set as a I/O pin. Datasheet: http://coecsl.ece.illinois.edu/ge423/datasheets/MSP430Ref_Guides/msp430g2553datasheet.pdf
P1REN = 0x0; // No resistors enabled for Port 1
P1DIR &= ~0x9; // Set P1.0 P1.3 to intput to Read IR Sensor data on LaunchPad board. Make sure shunt jumper is in place at LaunchPad's Red LED
// Initialize Pordt 2 to be PWM set p2.1 and p2.4 as PWM
P2SEL |= BIT1+BIT4;
P2SEL2 &= ~(BIT1+BIT4);
P2DIR |= BIT1+BIT4;
// Timer A Config
TACCTL0 = CCIE; // Enable Periodic interrupt
TACCR0 = 16000; // period = 1ms
TACTL = TASSEL_2 + MC_1; // source SMCLK, up mode
TA1CCR0 = 40000; // set carrier frequency to 50Hz period = 20 ms
TA1CCTL1 = OUTMOD_7; // TA1CCR1 reset/set
TA1CCTL2 = OUTMOD_7; // TA1CCR2 reset/set
TA1CCTL0 = 0;
TA1CTL = TASSEL_2 + ID_3 + MC_1; // SMCLK, up mode, divider 8 so 20000 = 1 ms
ADC10CTL1 = INCH_3 + ADC10SSEL_3 + CONSEQ_1; //INCH_3: Enable A3 first, Use SMCLK, Sequence of Channels
ADC10CTL0 = ADC10ON + MSC + ADC10IE; // Turn on ADC, Put in Multiple Sample and Conversion mode, Enable Interrupt
ADC10AE0 |= 0x09; // Enable A0 and A3 which are P1.0,P1.3
ADC10DTC1 = 4; // Four conversions. Only A3 and A0 are being used.
ADC10SA = (short)&ADC[0]; // ADC10 data transfer starting address.
Init_UART(115200,1); // Initialize UART for 9600 baud serial communication
_BIS_SR(GIE); // Enable global interrupt
while(1) {
if(newmsg) {
newmsg = 0;
}
if (newprint) {
newprint = 0;
}
if (newADC == 1) {
UART_printf("0:%d 3:%d time: %d spraycount = %d\n\r",A0value,A3value,timecount,spraycount); // Print to UART
newADC = 0;
}
}
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
timecnt++; // Keep track of time for main while loop.
if ((timecnt%500) == 0) {
ADC10CTL0 |= ENC + ADC10SC; // Enable Sampling and start conversion.
}
if ((timecnt%500) == 0) {
newprint = 1; // flag main while loop that .5 seconds have gone by.
}
}
//ADC10 interrupt Service Routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void) {
A0value = 4095 - ADC[3]*4095L/1023; // We read in the value of IR sensor in A0 port and store it in A0value
A3value = 4095 - ADC[0]*4095L/1023; // We read in the value of IR sensor in A3 port and store it in A3value
ADC10CTL0 &= ~ADC10IFG; // clear interrupt flag
ADC10SA = (short)&ADC[0]; // ADC10 data transfer starting address.
newADC = 1;
switch (statevar){
case 1:
TA1CCR2 = 4000; // move IR sensor to right
timecount++; //increment time
if (timecount > 5) { //If pigeon is still right of the fixture for 4 seconds, press the nozzle by moving the top servo
TA1CCR1 = 5000; // Move top servo
spraycount++; // increment timer that counts how much time elapsed till pressed.
timecount = 0;
}
if (spraycount > 1) { //If nozzle has been pressed release the nozzle by moving the servo back.
TA1CCR1 = 3000; // reset top servo
spraycount = 0; //reset the spray count
}
if (A0value > 2200) { //if no object sensed in right servo go back to initial state (2)
timecount = 0;
statevar = 2;
}
break;
case 2: //Initialized as 2. When no pigeon as been detected.
TA1CCR1 = 3000;
TA1CCR2 = 3000;
timecount = 0;
if ((A3value > 2200) && (A0value < 2200)){ // if IR sensor in A0 is low
statevar = 1; //change state to move pepper spray to right
}
if ((A3value < 2200) && (A0value > 2200)){ // if IR sensor in A3 is low
statevar = 3; //change state to move pepper spray to left
}
break;
case 3:
TA1CCR2 = 2000;// move IR sensor to left
timecount++;//increment time
if (timecount > 5) {//If pigeon is still right of the fixture for 4 seconds, press the nozzle by moving the top servo
TA1CCR1 = 5000;// Move top servo
spraycount++;// increment timer that counts how much time elapsed till pressed.
timecount = 0;
}
if (spraycount > 1) { //If nozzle has been pressed release the nozzle by moving the servo back
TA1CCR1 = 3000; // reset top servo
spraycount = 0; //reset the spray count
}
if (A3value > 2200) {//if no object sensed in right servo go back to initial state (2)
timecount = 0;
statevar = 2;
}
break;
}
}
// 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) { // 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++;
}
} else { // interrupt after sendchar call so just set senddone flag since only one char is sent
senddone = 1;
}
IFG2 &= ~UCA0TXIFG;
}
if(IFG2&UCB0TXIFG) { // USCI_B0 requested TX interrupt (UCB0TXBUF is empty)
IFG2 &= ~UCB0TXIFG; // clear IFG
}
}
// 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&UCB0RXIFG) { // USCI_B0 requested RX interrupt (UCB0RXBUF is full)
IFG2 &= ~UCB0RXIFG; // clear IFG
}
if(IFG2&UCA0RXIFG) { // USCI_A0 requested RX interrupt (UCA0RXBUF is full)
// Uncomment this block of code if you would like to use this COM protocol that uses 253 as STARTCHAR and 255 as STOPCHAR
/* 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;
}
}
Comments