首页 论坛 原厂专区 TI MCU MSP430x14x模糊逻辑马达控制-源程序,已通过测试

发帖 回复

[资料] MSP430x14x模糊逻辑马达控制-源程序,已通过测试
645 查看
7 回复
 楼主 | 发布于 2018-08-29 | 只看楼主
分享到:
#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 )
评论 (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 )
评论 (0) 举报

楼主 | 回复于 2018-08-29 3#

所有代码是一个c文件,因为发帖字数限制分成了三个楼层
(0 )
评论 (0) 举报

回复于 2018-08-30 4#

谢谢分享!!!!!!!!!!!
(0 )
评论 (0) 举报

回复于 2018-08-30 5#

谢谢分享
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-30 6#

感谢分享
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-30 7#

一起分享
(0 )
评论 (0) 举报
  • 发表回复
    0/3000





    举报

    请选择举报类别

    • 广告垃圾
    • 违规内容
    • 恶意灌水
    • 重复发帖

    全部板块

    返回顶部