cannon

//
// This is a dsPIC30F4011 program for an open day demo
//
// written by Ted Burke - last updated 1-12-2011
//
// PLEASE NOTE:
//
// The stdio.h functions, such as printf, require a 'heap' to be
// allocqated (basically, a heap is a block of memory reserved for
// data storage). I set my heap size to 512 in MPLAB's project
// settings dialog box, as follows:
//
//     Project->Build Options...->Project->MPLAB LINK30->Heap size = 512
//

#include <libpic30.h>
#include <p30f4011.h>
#include <stdio.h>
#include <math.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

// Function prototypes
void configure_pins();
unsigned int read_analog_channel(int n);

// Stepper angle variable and functions
int angle = 0;
void step_to_angle(int);
void step_right();
void step_left();
long step_delay = 100000;
int range_threshold = 100; // About 30cm ish

int main()
{
	// variable declarations
	char c;         // Character to receive text via UART
	int n, v;

	// Set up digital i/o, analog input, PWM, UART and interrupt
	configure_pins();

	// States
	// 0. Reverse to zero
	// 1. Search right
	// 2. Reverse left
	// 3. Search left
	// 4. Reverse right
	int state = 0;
	int counter = 0;
	while(1)
	{
		if (state == 0)
		{
			step_left();
			if (angle < -100)
			{
				angle = 0;
				state = 5;
			}
		}
		else if (state == 5)
		{
			__delay32(60000000);
			while(1)
			{
				step_to_angle(100);
				__delay32(30000000);
				step_to_angle(50);
				__delay32(30000000);
				step_to_angle(0);
				__delay32(30000000);
			}
		}
		else if (state == 1)
		{
			step_right();
			if (read_analog_channel(0) > 100)
			{
				_LATC13 = 1; // LED on
				state = 2;
			}
		}
		else if (state == 2)
		{
			step_left();
			if (read_analog_channel(0) <= 100)
			{
				_LATC13 = 0; // LED off
				state = 1;
			}
		}
		else if (state == 3)
		{
			step_left();
			if (read_analog_channel(0) > 100)
			{
				_LATC13 = 1; // LED on
				state = 4;
			}
		}
		else if (state == 4)
		{
			step_left();
			if (read_analog_channel(0) <= 100)
			{
				_LATC13 = 0; // LED off
				state = 3;
			}
		}
	}

	while(1)
	{
		if (read_analog_channel(0) > 100) _LATC13 = 1;
		else _LATC13 = 0;
	}

	while(1)
	{
		step_to_angle(100);
		__delay32(10000000);
		step_to_angle(25);
		__delay32(10000000);
		step_to_angle(75);
		__delay32(10000000);
		step_to_angle(0);
		__delay32(10000000);
	}

	while(1)
	{
		for (n = 0 ; n < 100 ; ++n) step_right();
		for (n = 0 ; n < 100 ; ++n) step_left();
	}

	// Flash LEDs on RD0 and RD1 at 1Hz for 4 seconds
	for (n=0 ; n<4 ; ++n)
	{
		_LATD0 = 0; _LATD1 = 0;
		__delay32(15000000);
		_LATD0 = 1; _LATD1 = 1;
		__delay32(15000000);
	}

	while(1)
	{
		v = read_analog_channel(0);
		printf("Range finder sensor = %04d,", v);

		// 20ms delay
		__delay32(600000);

		// Check if any characters were received via UART
		if (U1STAbits.URXDA == 1)
		{
			// If a '1' or '0' were received, set RD0 and RD1
			c = U1RXREG;
			if (c == '1') {_LATD0 = 1; _LATD1 = 1;}
			if (c == '0') {_LATD0 = 0; _LATD1 = 0;}
		}
	}

	return 0;
}

void step_right()
{
	if (LATD == 0b0000) LATD = 0b0001;
	else if (LATD == 0b0001) LATD = 0b0100;
	else if (LATD == 0b0100) LATD = 0b0010;
	else if (LATD == 0b0010) LATD = 0b1000;
	else if (LATD == 0b1000) LATD = 0b0001;

	angle++;

	__delay32(step_delay);
}

void step_left()
{
	if (LATD == 0b0000) LATD = 0b0001;
	else if (LATD == 0b0100) LATD = 0b0001;
	else if (LATD == 0b0010) LATD = 0b0100;
	else if (LATD == 0b1000) LATD = 0b0010;
	else if (LATD == 0b0001) LATD = 0b1000;

	angle--;

	__delay32(step_delay);
}

void step_to_angle(int target)
{
	while (angle < target) step_right();
	while (angle > target) step_left();
}

// This function sets up digital i/o, analog input, PWM,
// UART and timer interrupt.
void configure_pins()
{
	// Configure all four port D pins (RD0, RD1, RD2, RD3)
	// as digital outputs
	LATD = 0;
	TRISD = 0b1111111111110000;

	// Configure RC13 as output, RC14 and RC15 as inputs
	// as digital outputs
	TRISC = 0b1110111111111111;

	// Configure AN0-AN8 as analog inputs
	TRISB = 0x01FF;      // All 9 port B pins are inputs
	ADPCFG = 0xFE00;     // Lowest 9 PORTB pins are analog inputs
	ADCON1 = 0;          // Manually clear SAMP to end sampling, start conversion
	ADCON2 = 0;          // Voltage reference from AVDD and AVSS
	ADCON3 = 0x0005;     // Manual Sample, ADCS=5 -> Tad = 3*Tcy
	ADCON1bits.ADON = 1; // Turn ADC ON

	// Configure PWM for free running mode
	//
	//   PWM period = Tcy * prescale * PTPER = 0.33ns * 64 * PTPER
	//   PWM pulse width = (Tcy/2) * prescale * PDC
	//
	PWMCON1 = 0x00FF; // Enable all PWM pairs in complementary mode
	PTCON = 0;
	_PTCKPS = 3;      // prescale=1:64 (0=1:1, 1=1:4, 2=1:16, 3=1:64)
	PTPER = 9470;     // 20ms PWM period (15-bit period value)
	PDC1 = PTPER;     // 50% duty cycle on PWM channel 1
	PDC2 = PTPER;     // 50% duty cycle on PWM channel 2
	PDC3 = PTPER;     // 50% duty cycle on PWM channel 3
	PTMR = 0;         // Clear 15-bit PWM timer counter
	_PTEN = 1;        // Enable PWM time base

	// Set up UART
	// Default is 8 data bits, 1 stop bit, no parity bit
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART
	U1STAbits.UTXISEL = 1; // interrupt when TX buffer is empty
	U1STAbits.UTXEN = 1;   // Enable TX
}

// This function reads a single sample from the specified
// analog input. It should take less than 2.5us if the chip
// is running at about 30 MIPS.
// Because the dsPIC30F4011 has a 10-bit ADC, the value
// returned will be between 0 and 1023.
unsigned int read_analog_channel(int channel)
{
	ADCHS = channel;          // Select the requested channel
	ADCON1bits.SAMP = 1;      // Start sampling
	__delay32(30);            // 1us delay @ 30 MIPS
	ADCON1bits.SAMP = 0;      // Start Converting
	while (!ADCON1bits.DONE); // Should take 12 * Tad = 1.2us
	return ADCBUF0;
}

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s