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
}