Академический Документы
Профессиональный Документы
Культура Документы
**
DC_motor_xtal.c - run a DC motor at xtal "clockwork" locked speed
Started 8 Apr 2013 - Copyright www.RomanBlack.com, allowed for public use,
you must mention me as the author and please provide
a link to my web page where this system is described;
www.RomanBlack.com/onesec/DCmotor_xtal.htm
PIC configs; MCRLE off, BODEN off, BORES off, WDT off, LVP off, PWRT on
*****************************************************************************
*/
// This constant sets the motor speed. The value is in nanoSeconds per pulse,
// as we are using a quadrature encoder there are 4 pulses per encoder slot.
// My encoder had 36 slots, so that makes 36*4 or 144 pulses per revolution.
// Example; 1 motor rev per second = 144 pulses /sec.
// nS per pulse = 1 billion / 144 = 6944444
//#define MOTOR_PULSE_PERIOD 1736111 // 4 RPS
//#define MOTOR_PULSE_PERIOD 3472222 // 2 RPS
#define MOTOR_PULSE_PERIOD 6944444 // 1 RPS
//#define MOTOR_PULSE_PERIOD 13888889 // 0.5 RPS
// This constant sets the proportional gain. Basically it sets how much
// more PWM % is added for each pulse behind that the motor gets.
// ie; if set to 10, the PWM is increased by 10% for each pulse behind.
// Values must be within 1-50. Values of 10 or 16 worked well with
// low motor RPMs, for higher RPMs a smaller value like 2 to 8 can be used.
#define MOTOR_PROP_GAIN 10
// global vars
unsigned char rpos;
unsigned char enc_new; // holds motor's quadrature encoder data for testing
unsigned char enc_last;
unsigned long bres;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
void interrupt()
{
//------------------------------------------------------// This is TMR0 int, prescaled at 2:1 so we get here every 512 instructions.
// This int does the entire closed loop speed control;
// 1. updates encoder to see if motor has moved, records it position
// 2. updates reference freq generator, records its position
// 3. compares the two, sets PWM if motor lags behind reference
// 4. limit both counts, so they never roll, but still retain all error
//------------------------------------------------------// clear int flag straight away to give max safe time
INTCON.T0IF = 0;
mpos--;
enc_last = enc_new;
}
if(mlag >= (100/MOTOR_PROP_GAIN)) CCPR1L = 100; // full power if is too far behind
else CCPR1L = (mlag * MOTOR_PROP_GAIN);
}
else
{
CCPR1L = 0;
}
// 4. limit both counts, so they never roll, but still retain all error
if(rpos>250 || mpos>250)
{
rpos -= 50;
mpos -= 50;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
//============================================================================
=
// MAIN
//============================================================================
=
void main()
{
//------------------------------------------------------// setup PIC 16F628A
CMCON = 0b00000111;
PORTA = 0b00000000;
TRISA = 0b00000011;
PORTB = 0b00000000;
TRISB = 0b00000000;
//
// RA0,RA1 used for digital ST encoder inputs
//
// RB3 is CCP1 PWM out, RB0,RB1 are encoder echo outputs
// set TMR2 to roll every 100 ticks, PWM freq = 5mil/16/100 = 3125 Hz
T2CON = 0b00000111;
PR2 = (100-1);
// echo the two encoder pins out two spare PORTB digital outputs!
pins = 0;
if(PORTA.F0) pins.F0 = 1;
if(PORTA.F1) pins.F1 = 1;
PORTB = pins; // output those two pins only (PWM output is not affected)
}
}
//-----------------------------------------------------------------------------