Magnetic Accelerator Cannon

Source Code

The latest code for the control system

#include <msp430f5529.h>
#include <stdio.h>
#include "lcd.h"
#include <stdlib.h>
#include <string.h>
//HIGH THRESHOLD  ---- That particular value must be a voltage between Vcc and 2/3 of Vcc.
//Make sure everything is in the right port
//Triggers on Varying ports
#define TRIGG	BIT2				// P4.2
#define UP		BIT3				// P4.3
#define DOWN	BIT0				// P7.0

#define S1TRIGG BIT0				// P3.0
#define S2TRIGG BIT1				// P3.1
#define S3TRIGG BIT2				// P3.2
#define S4TRIGG BIT4				// P3.4
#define S5TRIGG BIT5				// P3.5
#define S6TRIGG BIT6				// P3.6
#define S7TRIGG BIT0				// P4.0
#define S8TRIGG BIT1				// P4.1

//Sensors have to be in P1 and P2 (they have interrupt capability)
#define S1SEN	BIT0	//1.0
#define S2SEN	BIT2	//1.2
#define S3SEN	BIT3	//1.3
#define S4SEN	BIT4	//1.4
#define S5SEN	BIT5	//1.5
#define S6SEN	BIT6	//1.6
#define S7SEN	BIT0	//2.0
#define S8SEN	BIT2	//2.2
#define S9SEN	BIT3	//2.3

//6.0-6.6 - LED

unsigned int fire_stage_1(void);
unsigned int fire_stage_2(void);
unsigned int fire_stage_3(void);
unsigned int fire_stage_4(void);
unsigned int fire_stage_5(void);
unsigned int fire_stage_6(void);
unsigned int fire_stage_7(void);
unsigned int fire_stage_8(void);

void start_firing_timer(void);
void measure_speed(void);

//"Global" variables
unsigned int current_stage = 0; //If zero means firing hasn't started
unsigned int stages_to_fire = 8; //Default value set by the UI

//Init LCD Stuff
/*
Ground - Pins 1 and 16
5V Supply - Pins 2 and 15
10K Potentiometer - Pin 3
P6.0 - D4 Pin11
P6.1 - D5 Pin12
P6.2 - D6 Pin13
P6.3 - D7 Pin14
P6.4 - RS Pin4
P6.5 - R/W Pin5
P6.6 - E Pin6
*/

int g;
int v=1;
int button_pressed=0;
int message_printed=0;
int h=0;
int k;
static char *i2a(unsigned i, char *a, unsigned r)
 {
   if (i/r > 0) a = i2a(i/r,a,r);
   *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
   return a+1;
 }

 char *itoa(int i, char *a, int r)
 {

   if ((r < 2) || (r > 36)) r = 10;
   if (i < 0)
   {
       *a = '-';
       *i2a(-(unsigned)i,a+1,r) = 0;
   }
   else *i2a(i,a,r) = 0;
   return a;
 }

char buffer[16];
//End LCD stuff



void update_display(void) {
	//Changes the Display depending on the selected number of stages
	send_command(0x0E); // clear the screen
	send_command(0x00); // display cursor oFF
	send_command(0x06); // increment cursor
	send_command(0x80); // row 1 column 1

	if (stages_to_fire == 8) {
		lcd_init();
		send_string("8 stages");
	} else if (stages_to_fire == 7) {
		send_string("7 stages");
	} else if (stages_to_fire == 6) {
		send_string("6 stages");
	} else if (stages_to_fire == 5) {
		send_string("5 stages");
	} else if (stages_to_fire == 4) {
		send_string("4 stages");
	} else if (stages_to_fire == 3) {
		send_string("3 stages");
	} else if (stages_to_fire == 2) {
		send_string("2 stages");
	} else if (stages_to_fire == 1) {
		send_string("1 stage");
	}
}

void main(void) {

	WDTCTL = WDTPW + WDTHOLD; 		// Stop watchdog timer

	lcd_init();
	update_display();

	printf("test\n");
	//Set all stage trigger directions (output)
	P3DIR |= S1TRIGG;
	P3DIR |= S2TRIGG;
	P3DIR |= S3TRIGG;
	P3DIR |= S4TRIGG;
	P3DIR |= S5TRIGG;
	P3DIR |= S6TRIGG;
	P4DIR |= S7TRIGG;
	P4DIR |= S8TRIGG;

	//Set all triggers to off
	P3OUT &= ~S1TRIGG;
	P3OUT &= ~S2TRIGG;
	P3OUT &= ~S3TRIGG;
	P3OUT &= ~S4TRIGG;
	P3OUT &= ~S5TRIGG;
	P3OUT &= ~S6TRIGG;
	P4OUT &= ~S7TRIGG;
	P4OUT &= ~S8TRIGG;

	//Select all sensor inputs
	P1SEL &= ~S1SEN;
	P1SEL &= ~S2SEN;
	P1SEL &= ~S3SEN;
	P1SEL &= ~S4SEN;
	P1SEL &= ~S5SEN;
	P1SEL &= ~S6SEN;
	P2SEL &= ~S7SEN;
	P2SEL &= ~S8SEN;
	P2SEL &= ~S9SEN;

	//Enable pull-up resistors on all sensor inputs
	P1REN |= S1SEN; //Stage 1 sensor
	P1REN |= S2SEN;
	P1REN |= S3SEN;
	P1REN |= S4SEN;
	P1REN |= S5SEN;
	P1REN |= S6SEN;
	P2REN |= S7SEN;
	P2REN |= S8SEN;
	P2REN |= S9SEN;

	//Set all sensor input directions
	P1DIR &= ~S1SEN; //Stage 1 sensor
	P1DIR &= ~S2SEN;
	P1DIR &= ~S3SEN;
	P1DIR &= ~S4SEN;
	P1DIR &= ~S5SEN;
	P1DIR &= ~S6SEN;
	P1DIR &= ~S7SEN;
	P2DIR &= ~S8SEN;
	P2DIR &= ~S9SEN;

	//Enable interrupt on all sensors
	P1IE |=S1SEN;
	P1IE |=S2SEN;
	P1IE |=S3SEN;
	P1IE |=S4SEN;
	P1IE |=S5SEN;
	P1IE |=S6SEN;
	P1IE |=S7SEN;
	P2IE |=S8SEN;
	P2IE |=S9SEN;

	//Clear all interrupt bits on all sensors
	P1IFG = 0;
	P2IFG = 0;

	//Select all user inputs
	//User interface works syncronously (no interrupts)
	P4DIR &= ~TRIGG;
	P4SEL &= ~TRIGG;
	P4REN |= TRIGG;

	P4DIR &= ~UP;
	P4SEL &= ~UP;
	P4REN |= UP;

	P7DIR &= ~DOWN;
	P7SEL &= ~DOWN;
	P7REN |= DOWN;

	_BIS_SR(GIE);	     		// Enable interrupts

	unsigned int i = 0;
	int toggle = 0;
	while(1) {
		if ((P4IN & TRIGG)) {  //NEEEDS DEBOUNCE!!!!
			if ((toggle == 1) && (current_stage == 0)) {
				i = 0;
				fire_stage_1();
				toggle = 0;
			}
		} else {
			toggle = 1;
		}
		if (i > 0x20000000-1000) { //Keeps the system from hanging in case of sensor malfunction
			i = 0;
			current_stage = 0;
		}
		if((P4IN & UP)) {
			if (stages_to_fire + 1 <= 8) {
				stages_to_fire++;
				update_display();
				printf("%d and Up\n", stages_to_fire);
			}

		}
		if ((P7IN & DOWN)) {
			if (stages_to_fire - 1 > 0 ) {
				stages_to_fire--;
				update_display();
				printf("%d and Down\n", stages_to_fire);
			}
		}
		i++;
	}
}

unsigned int firing_pulse = 50;

unsigned int fire_stage_1(void) {
	current_stage = 1;
	P3OUT |= S1TRIGG; 			// Turn P1.0 on
	start_firing_timer();
	return 0;
}

unsigned int fire_stage_2(void) {
	current_stage = 2;
	P3OUT |= S2TRIGG;
	//	P4OUT |= S2TRIGG; 			// Turn P1.0 on
	start_firing_timer();
	return 0;
}


unsigned int fire_stage_3(void) {
	current_stage = 3;
	P3OUT |= S3TRIGG;
	start_firing_timer();
	return 0;
}

unsigned int fire_stage_4(void) {
	current_stage = 4;
	P3OUT |= S4TRIGG;
	start_firing_timer();
	return 0;
}


unsigned int fire_stage_5(void) {
	current_stage = 5;
	P3OUT |= S5TRIGG;
	start_firing_timer();
	return 0;
}


unsigned int fire_stage_6(void) {
	current_stage = 6;
	P3OUT |= S6TRIGG;
	start_firing_timer();
	return 0;
}


unsigned int fire_stage_7(void) {
	current_stage = 7;
	P4OUT |= S7TRIGG;
	start_firing_timer();
	return 0;
}


unsigned int fire_stage_8(void) {
	current_stage = 8;
	P4OUT |= S8TRIGG;
	start_firing_timer();
	return 0;
}

void start_firing_timer(void) { //Keeps the thyristor gate open for firing_pulse amount of time
	TA1CCR0 = firing_pulse;		// Amount of time thyristor gate is supposed to be open (with some uncertainty from other synchronous stuff)
	TA1CCTL0 = 0x10;			// Enable counter interrupts, bit 4=1
	TA1CTL = TASSEL_2 + MC_1;  	//Counting up to TACCR0
}

void measure_speed(void) {
	float final_speed;
	const int SENSOR_DISTANCE = 30.0; //SENSOR DISTANCE in mm
	//Measures the muzzle velocity of the projectile
	TA0CTL = TASSEL_2 + MC_2;
	while(!(P2OUT & S9SEN)) {
		//Wait up
	}
	TA0CTL = TASSEL_2 + MC_0;
	float final_period = TA0R; //In microsecondsish
	final_speed = (float)SENSOR_DISTANCE/((float)final_period/1000);
	//Output final speed to screen
}


// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void) {
	//P1IFG &= ~S1SEN; 			// Clear interrupt flag
	P1IFG = 0; //Clear all Port 1 interrupts
	if (current_stage < stages_to_fire) {
		if (current_stage == 1) {
			fire_stage_2();
		} else if (current_stage == 2) {
			fire_stage_3();
		} else if (current_stage == 3) {
			fire_stage_4();
		}else if (current_stage == 4) {
			fire_stage_5();
		} else if (current_stage == 5) {
			fire_stage_6();
		} else if (current_stage == 6) {
			fire_stage_7();
	}
}}

// Port 2 interrupt service routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void) {
	P2IFG = 0; //Clear all Port 1 interrupts
	if (current_stage == 7) {
		fire_stage_8();
	} else if (current_stage == 8) {
		//measure the speed
		measure_speed();
	}
}

#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0(void) {
	TA1CTL = TASSEL_2 + MC_0; //Stop the clock
	if (current_stage == 1) {
		P3OUT &= ~S1TRIGG; //Turn P1.0 off
	} else if (current_stage == 2) {
		P3OUT &= ~S2TRIGG;
	} else if (current_stage == 3) {
		P3OUT &= ~S3TRIGG;
	} else if (current_stage == 4 ) {
		P3OUT &= ~S4TRIGG;
	} else if (current_stage == 5) {
		P3OUT &= ~S5TRIGG;
	} else if (current_stage == 6) {
		P3OUT &= ~S6TRIGG;
	} else if (current_stage == 7) {
		P4OUT &= ~S7TRIGG;
	} else if (current_stage == 8) {
		P4OUT &= ~S8TRIGG;
	} else {
		_NOP();
	}
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0(void) {
	TA0CTL = TASSEL_2 + MC_0; //Stop the clock

}