PK ’†'b b ) RC Servo Processor\RC Servo Processor.mcp[HEADER]
magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13}
file_version=1.0
device=PIC12F683
[PATH_INFO]
BuildDirPolicy=BuildDirIsProjectDir
dir_src=
dir_bin=
dir_tmp=
dir_sin=
dir_inc=
dir_lib=
dir_lkr=
[CAT_FILTERS]
filter_src=*.c;*.as;*.asm;*.usb
filter_inc=*.h;
filter_obj=*.obj;*.p1;*.hex
filter_lib=*.lib;*.lpp
filter_lkr=*.unknown
[CAT_SUBFOLDERS]
subfolder_src=
subfolder_inc=
subfolder_obj=
subfolder_lib=
subfolder_lkr=
[FILE_SUBFOLDERS]
file_000=.
[GENERATED_FILES]
file_000=no
[OTHER_FILES]
file_000=no
[FILE_INFO]
file_000=main.c
[SUITE_INFO]
suite_guid={507D93FD-16F1-4270-980F-0C7C0207E6D3}
suite_state=
[TOOL_SETTINGS]
TS{3FF1D5F2-E530-4850-9F70-F61D55BD1AC9}=C9=5,4,3,2,1
[INSTRUMENTED_TRACE]
enable=0
transport=0
format=0
[CUSTOM_BUILD]
Pre-Build=
Pre-BuildEnabled=1
Post-Build=
Post-BuildEnabled=1
PK ütÊù ù RC Servo Processor\main.c/************************************************************************
main.c
RC Servo Processor
Copyright (C) 2011 Simon Inns
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Email: simon.inns@gmail.com
************************************************************************/
#ifndef MAIN_C
#define MAIN_C
// Global includes
#include
// Fuse configuration for the PIC12F683
__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & MCLREN &
PWRTDIS & WDTDIS & INTIO);
// Define oscillator frequency
#define _XTAL_FREQ 8000000
// Hardware mapping definitions
#define RC_RECEIVER_IN GPIO2
#define RC_SERVO_OUT GPIO5
// Useful definitions
#define OFF 0
#define ON 1
#define FALSE 0
#define TRUE 1
// Definitions for RC Receiver input (in units of 0.5uS)
// 1146uS to 1889 uS
#define RX_MIN_WIDTH 1146*2
#define RX_MAX_WIDTH 1889*2
// Definitions for RC Servo output (in units of 0.5uS)
// 400uS to 2150uS
#define SERVO_MIN_WIDTH 400*2
#define SERVO_MAX_WIDTH 2150*2
// Rotational Speed limitation for output servo
// Set to zero for no limit or specify the maximum allowed pulse width variation
// per output pulse (in units of 0.5uS). Note: the actual speed of the output
// pulses is dependent on the RC Receiver output, but is typically one pulse per
// 20mS (50 pulses per second).
#define SERVO_SPEED_LIMIT 0
// Number of samples to average the positive pulse width from (2-5)
#define NO_OF_SAMPLES 4
// Main procedure
void main(void)
{
OSCCON = 0b01110001; // 8Mhz INT OSC
// Set up the PIC12F683 IO pins
GPIO = 0b00000000; // Set all pins to zero
ANSEL = 0b00000000; // Disable analogue inputs
TRISIO = 0b00000100; // GPIO2 is input, all other pins output
OPTION = 0b00000000; // Set the option register (page 12 of DS)
WPU = 0b00000000; // Set weak pull-up off on all pins
CMCON0 = 7; // Disable comparator 0
// Configure timer1 for use with the Capture/Compare module
// Fosc is 8 Mhz so Fosc/4 is 2,000,000 timer ticks per second.
// We are using a 1:1 prescaler so each timer tick is 0.5uS
TMR1IF = 0; // Reset the timer1 interrupt flag
T1SYNC = 0;
T1CON = 0b00000000; // Turn the timer off
TMR1IE = 0; // Turn the timer1 interrupt off
TMR1H = 0x00;
TMR1L = 0x00;
// Configure the Capture/Compare module
CCP1CON = 0b00000101; // Capture mode every rising edge of GPIO2
CCP1IE = 0; // CCP interrupt disabled
CCP1IF = 0; // Clear the capture flag
// Variables for calculating the require pulse width
int inputPulseWidth = 0;
int outputPulseWidth = 0;
int previousPulseWidth = -1;
// Variables for averaging the measurements
int averagePulseWidth = 0;
int cumlativeTotal = 0;
int sampleNumber = 0;
while(1)
{
// Read the RC receiver pulse width ---------------------------------------------
// Reset timer1
T1CON = 0b00000000;
TMR1IF = 0;
TMR1H = 0x00;
TMR1L = 0x00;
// Wait for the rising edge of the PWM signal from the RC receiver
CCP1CON = 0b00000101; // Capture mode every rising edge of GPIO2
CCP1IF = 0; // Clear the capture flag
while(!CCP1IF); // Wait for the capture flag
// Now time the width of the pulse to the trailing edge
CCP1CON = 0b00000100; // Capture mode every falling edge of GPIO2
T1CON = 0b00000001; // Turn the timer on
CCP1IF = 0; // Clear the capture flag
while(!CCP1IF); // Wait for the capture flag
// Get the current pulse width from CCP1 (in 0.5uS units)
inputPulseWidth = CCPR1H << 8;
inputPulseWidth += CCPR1L;
// Average out the pulse width measurement --------------------------------------
if (averagePulseWidth != 0)
{
cumlativeTotal += inputPulseWidth;
sampleNumber++;
if (sampleNumber == NO_OF_SAMPLES)
{
sampleNumber = 0;
cumlativeTotal = cumlativeTotal / NO_OF_SAMPLES;
averagePulseWidth = cumlativeTotal;
cumlativeTotal = 0;
}
}
else averagePulseWidth = inputPulseWidth;
// Calculate the required output pulse width ------------------------------------
// Range check the input pulse width
if (averagePulseWidth < RX_MIN_WIDTH) averagePulseWidth = RX_MIN_WIDTH;
if (averagePulseWidth > RX_MAX_WIDTH) averagePulseWidth = RX_MAX_WIDTH;
// Calculate the input width range
int averagePulseWidthRange = RX_MAX_WIDTH - RX_MIN_WIDTH;
// Calclulate the output width range
int outputPulseWidthRange = SERVO_MAX_WIDTH - SERVO_MIN_WIDTH;
// Subtract the minimum input pulse width to make the input width value start from 0
int averagePulseWidthFromZero = averagePulseWidth - RX_MIN_WIDTH;
// Calculate the required scaling amount to get from the input range to the output range
float inputScale = (float)outputPulseWidthRange / (float)averagePulseWidthRange;
// Scale the input pulse width
float outputValue = (float)averagePulseWidthFromZero * (float)inputScale;
// Add the servo out minimum width to get the final required value
outputPulseWidth = (int)outputValue + SERVO_MIN_WIDTH;
// Limit the rotational speed of the output servo (if required) -----------------
// If this is the first pass, set the previousPulseWidth to the current width
if (previousPulseWidth == -1) previousPulseWidth = outputPulseWidth;
// Only limit the speed if the limit is not zero (off)
if (SERVO_SPEED_LIMIT != 0)
{
// Are we moving in a positive direction?
if (outputPulseWidth >= previousPulseWidth)
{
if ((previousPulseWidth + SERVO_SPEED_LIMIT) < outputPulseWidth)
outputPulseWidth = previousPulseWidth + SERVO_SPEED_LIMIT;
if (outputPulseWidth >= SERVO_MAX_WIDTH) outputPulseWidth = SERVO_MAX_WIDTH;
}
else
{
// We moving in a negative direction
if ((previousPulseWidth - SERVO_SPEED_LIMIT) > outputPulseWidth)
outputPulseWidth = previousPulseWidth - SERVO_SPEED_LIMIT;
if (outputPulseWidth <= SERVO_MIN_WIDTH) outputPulseWidth = SERVO_MIN_WIDTH;
}
// Store the current position in the previous
previousPulseWidth = outputPulseWidth;
}
// Output the RC Servo pulse ----------------------------------------------------
// Turn timer1 off and reset the interrupt flag
T1CON = 0b00000000;
TMR1IF = 0;
// Set timer1 to overflow according to the required pulse width
outputPulseWidth = 65535 - outputPulseWidth;
TMR1H = (outputPulseWidth & 0xFF00) >> 8; // Set high byte
TMR1L = (outputPulseWidth & 0x00FF); // Set low byte
// Output the pulse
T1CON = 0b00000001; // Turn the timer on
RC_SERVO_OUT = 1; // Pulse out high
while(!TMR1IF); // Wait for overflow
RC_SERVO_OUT = 0; // Pulse out low
}
}
#endifPK ’†'b b ) RC Servo Processor\RC Servo Processor.mcpPK ütÊù ù © RC Servo Processor\main.cPK ž Ù