//
// 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;
}
Like this:
Like Loading...