分享到:
#include "msp430x14x.h"
#define PWM_Period 3999 // 8MHz / 4000 = 2kHz
#define PWM_Max 1199 // Max duty factor used
#define PWM_Min 149 // Min duty factor used
#define MIN_SPEED 10000 // Min. measured speed
int Array[700]; // Debug buffer
int pArray = 0;
unsigned int SetSpeed = 1667; // 1667 equal 50rpsec
// SetSpeed = f_Timer / (RevPerSec * 24)
// with f_Timer = 2MHz
unsigned int LastTACCR; // Speed measurement vars
unsigned int CurrentSpeed = MIN_SPEED;
unsigned long SpeedMemSum = 8 * (unsigned long)MIN_SPEED;
unsigned int pSpeedMem = 0;
unsigned int SpeedMem[8] =
{
MIN_SPEED, MIN_SPEED, MIN_SPEED, MIN_SPEED,
MIN_SPEED, MIN_SPEED, MIN_SPEED, MIN_SPEED
};
long Error; // Control algorithm vars
long dError;
long LastError;
long PWMValue;
int X1[5]; // Fuzzy control variables
int X2[5];
int Y[5];
int Output;
#define NM 0 // negative medium
#define NS 1 // negative small
#define ZE 2 // zero equal
#define PS 3 // positive small
#define PM 4 // positive medium
const unsigned char InferenceTable[5][5] =
{
{ PM, PM, PM, PS, ZE },
{ PM, PM, PS, ZE, NS },
{ PM, PS, ZE, NS, NM },
{ PS, ZE, NS, NM, NM },
{ ZE, NS, NM, NM, NM }
};
const signed char OutputFunc[5] =
{
-0x10, -0x08, 0, 0x08, 0x10
};
// Function prototypes
void InitSystem(void);
void Fuzzification(int Value, int *Data);
void FuzzyInference(int *Error, int *dError, int *Y);
int Defuzzification(int *Y);
__interrupt void WDT_ISR(void);
__interrupt void TimerA0_ISR(void);
__interrupt void TimerA1_ISR(void);
void main(void)
{
volatile unsigned int i;
InitSystem();
while (1)
{
__bis_SR_register(LPM0_bits); // Enter LPM, wait for start of
// next control cycle
// If Error > 0 then motor is to fast
// If Error < 0 then motor is to slow
LastError = Error;
__disable_interrupt(); // Protect following statements
Error = (long)SetSpeed - CurrentSpeed; // Calc absolute error
if (pArray < sizeof Array/sizeof Array[0]) // Store some values for debug
Array[pArray++] = CurrentSpeed;
__enable_interrupt();
Error <<= 3; // Multiply by 8
dError = Error - LastError; // Calc differential error
dError <<= 5; // Multiply by 32
// Ensure error is within Fuzzy boundaries
if (Error > 0xc00) // Motor too fast?
{
TBCCR2 = PWM_Min; // Set PWM to minimum
continue; // Skip over control algorithm
}
if (Error < -0xc00) // Motor too slow?
{
TBCCR2 = PWM_Max; // Set PWM to maximum
continue; // Skip over control algorithm
}
Fuzzification(Error, X1); // Transform absolute error
Fuzzification(dError, X2); // Transform differential error
FuzzyInference(X1, X2, Y); // Apply Fuzzy rule table
Output = Defuzzification(Y); // Obtain scalar result
PWMValue = TBCCR2 + Output;
if (PWMValue < PWM_Min) PWMValue = PWM_Min; // Limit output value
if (PWMValue > PWM_Max) PWMValue = PWM_Max;
TBCCR2 = PWMValue; // Assign new PWM duty cycle
}
}
//------------------------------------------------------------------------------
// Function converts the discrete input value 'Value' into the 5-element
// Fuzzy vector Data[].
//------------------------------------------------------------------------------
void Fuzzification(int Value, int *Data)
{
int i;
for (i = 0; i < 5; i++)
Data[i] = 0;
if (Value < -0x800)
Data[NM] = 0x400;
else if (Value < -0x400)
{
Data[NM] = 0x400 - (Value + 0x800);
Data[NS] = Value + 0x800;
}
else if (Value < 0)
{
Data[NS] = 0x400 - (Value + 0x400);
Data[ZE] = Value + 0x400;
}
else if (Value < 0x400)
{
Data[ZE] = 0x400 - Value;
Data[PS] = Value;
}
else if (Value < 0x800)
{
Data[PS] = 0x400 - (Value - 0x400);
Data[PM] = Value - 0x400;
}
else
Data[PM] = 0x400;
}
//------------------------------------------------------------------------------
// Function applies the Fuzzy control interference rule table InferenceTable[][]
// to the two input arrays X1[] and X2[] to generate the output vector Y[].
//------------------------------------------------------------------------------
void FuzzyInference(int *X1, int *X2, int *Y)
{
int min[5];
int max;
int maxpos;
int i, j;
for (i = 0; i < 5; i++) // Clear output vector Y[]
Y[i] = 0;
for (i = 0; i < 5; i++) // Loop through X1[]
{
for (j = 0; j < 5; j++) // Loop through X2[]
if (X1[i] < X2[j]) // Determine smaller value,
min[j] = X1[i]; // store into min[]
else
min[j] = X2[j];
max = min[0]; // Find maximum in min[]
maxpos = 0;
for (j = 1; j < 5; j++)
if (max < min[j])
{
max = min[j]; // Store maximum
maxpos = j; // Store position of maximum
}
if (max > Y[InferenceTable[i][maxpos]]) // Apply inference table
Y[InferenceTable[i][maxpos]] += max;
if (Y[InferenceTable[i][maxpos]] > 0x400) // Limit output vector elements
Y[InferenceTable[i][maxpos]] = 0x400;
}
}
(0 )
(0 )
回复
举报
楼主
|
回复于 2018-08-29
沙发
//------------------------------------------------------------------------------
// Function transforms the Fuzzy vector Y[] to a discrete value using the
// center of gravity method.
//------------------------------------------------------------------------------
int Defuzzification(int *Y)
{
int i;
int ReturnVal = 0;
int SumY = 0;
for (i = 0; i < 5; i++)
{
SumY += Y[i];
ReturnVal += Y[i] * OutputFunc[i];
}
return ((long)ReturnVal << 2) / SumY; // Scale result by 4
}
//------------------------------------------------------------------------------
// MSP430-specific initialization of clock system and timer modules
//------------------------------------------------------------------------------
void InitSystem(void)
{
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // Hold WDT
// Setup Clock System
BCSCTL1 |= XTS; // ACLK=LFXT1=HF XTAL
do {
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
} while (IFG1 & OFIFG); // OSCFault flag still set?
BCSCTL2 |= SELM_3; // MCLK=LFXT1 (safe)
// Setup Ports
P2SEL = 0x04; // Assign P2.2 to Timer_A.CCI0B
P4SEL = 0x04; // Assign P4.2 to Timer_B.OUT2
P4DIR = 0x04; // P4.2 output
// Setup Timer_A for speed measurement
TACCR1 = MIN_SPEED; // Set minimum speed that is read out
TACCTL0 = CM_1 + CCIS_1 + SCS + CAP + CCIE; // Capture rising edge of CCI0B, interrupt
TACCTL1 = CCIE; // Compare mode, interrupt on EQU1
TACTL = TASSEL_1 + ID_2 + MC_2; // Use ACLK/4=2MHz, start in continuos mode
// Setup Timer_B for PWM generation
TBCCR0 = PWM_Period; // PWM Period
TBCCTL2 = OUTMOD_7 + CLLD0; // Set OUT2 on EQU0, reset on EQU1,
// sync latch load with EQU0
TBCTL = TBSSEL_1 + MC_1; // Use ACLK, start in up-mode
// Setup WDT for periodic interrupt
WDTCTL = WDTPW + WDTTMSEL + WDTSSEL; // Intervall timer, 8MHz/32768=244Hz
IE1 |= WDTIE;
__enable_interrupt();
}
(0 )
楼主
|
回复于 2018-08-29
2#
//------------------------------------------------------------------------------
// The Watchdog-timer ISR is used to periodically wake-up from low-power mode
// LPM0 to execute the Fuzzy control loop.
//------------------------------------------------------------------------------
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
__bic_SR_register_on_exit(LPM0_bits); // Wake up from LPM
}
//------------------------------------------------------------------------------
// The Timer_A CCR0 ISR is called on each TACCR0 capture event to obtain
// the time stamp of the input signal transition. An 8-tap moving average
// filter is used to minimize measurement error.
//------------------------------------------------------------------------------
#pragma vector = TIMERA0_VECTOR
__interrupt void TimerA0_ISR(void)
{
SpeedMemSum -= SpeedMem[pSpeedMem]; // Remove oldest value
SpeedMem[pSpeedMem] = (unsigned int)(TACCR0 - LastTACCR); // Replace with current
SpeedMemSum += SpeedMem[pSpeedMem++]; // Update running sum
CurrentSpeed = SpeedMemSum >> 3; // Calc speed by div 8
pSpeedMem &= 0x07; // Adjust circular pointer
LastTACCR = TACCR0;
TACCR1 = LastTACCR + MIN_SPEED; // Set timeout for minimum speed
} // to be read out
//------------------------------------------------------------------------------
// The Timer_A CCR1 ISR is called on TACCR1 compare events, which are generated
// when no input signal change is detected within 'MIN_SPEED' clock ticks after
// the last TACCR0 event. This provides a timeout function to update the speed
// variables in the case the motor gets halted.
//------------------------------------------------------------------------------
#pragma vector = TIMERA1_VECTOR
__interrupt void TimerA1_ISR(void)
{
switch (TAIV)
{
case 0x02 : // TACCR1 CCIFG
SpeedMemSum -= SpeedMem[pSpeedMem]; // Remove oldest value
SpeedMem[pSpeedMem] = (unsigned int)(TACCR1 - LastTACCR); // Replace with current
SpeedMemSum += SpeedMem[pSpeedMem++]; // Update running sum
CurrentSpeed = SpeedMemSum >> 3; // Calc speed by div 8
pSpeedMem &= 0x07; // Adjust circular pointer
LastTACCR = TACCR1;
TACCR1 = LastTACCR + MIN_SPEED; // Set timeout for minimum speed
break; // to be read out
}
}
(0 )
发表回复
版
块
导
航
块
导
航
举报
请选择举报类别
- 广告垃圾
- 违规内容
- 恶意灌水
- 重复发帖

发帖
回复