Fuzzy Logic управление электродвигателем с помощью контроллера MSP430x14x

Fuzzy Logic управление электродвигателем с помощью контроллера  MSP430x14x

В данной статье рассматривается реализация алгоритма управления на базе нечеткой логики с помощью микроконтроллера MSP430F14x.

Поскольку все семейства MSP430 совместимы снизу-вверх, то программа без труда может быть адаптирована и для других моделей контроллеров MSP430.

Алгоритмы управления на основе нечеткой логики могут быть использованы для решения вопросов, которые трудно решить традиционными методами управления. В качестве примера, демонстрируется универсальная последовательная система управления частотой вращения двигателя .

Контроль скорости вращения серийных универсальных двигателей очень сложный, когда реализуется с использованием традиционных методов управления, так как требует очень сложную математическую модель. Использование нечеткой логики устраняет необходимость математического моделирования и позволяет легко реализовать подобные решения. Нечеткая логика предоставляет правила, которые определяют поведение системы с помощью описания словами вместо математических уравнений. Алгоритм состоит из трех этапов:



1. фаззификации

2. Нечеткие определение

3. дефаззификация



В следующих разделах этой главы кратко обсудим эти три процесса. Для получения более подробной информации,

пожалуйста, обратитесь к [1].



Фаззификация это процесс, который определяет степень принадлежности входных значений к определенным нечетким множествам (лингвистическим переменным). В случае управления скоростью вращения серийных универсальных двигателей:


Входные значения:
1. Абсолютная погрешность скорости вращения:
Error = SetSpeed - CurrentSpeed
2. Дифференциальная ошибка скорости вращения.

Это значение получается путем вычитания предыдущего значения ошибки из текущего значения ошибки:

dError = Error- LastError

В нашем примере, пять нечетких множеств устанавливают границы для ввода значений Error и dError:



1. НМ: отрицательное среднее
2. NS: отрицательное малое
3. ZE: равно нулю

4. PS: положительное малое

5. PM: положительное среднее


Функции принадлежности (рис 1) треугольной формы, а максимальное значение масштабируется до 400H вместо 1, которое содержится в других документах, описывающих нечеткое теорию. Таким образом, сложность расчета значительно снижается, поскольку операция умножения становится только одним сложением или вычитанием.




Рис. 1. Функция принадлежности



Результатом фаззификации входного значения является вектор с пятью элементами, как пять нечетких множеств, и значение каждого элемента определяет степень принадлежности входного значения к конкретному нечеткому множеству (Y-значение). Векторы для абсолютных и дифференциальных ошибок, которые являются результатом фаззификации обозначаются как
X1 [ ] и Х2 [ ].
Например:
Пусть ошибка Error будет 30h и dError будет 10h. В этом случае в соответствии с Рисунком 2 и Рисунком 3, результатами фаззификации являются:



X1[ ] = [0h, 0h, 3D0h, 30h, 0h]

X2[ ] = [0h, 0h, 3F0h, 10h, 0h]




Рис. 2. Функция принадлежности Error (X1[ ])





Рис. 3. Функция принадлежности dError (X2[ ])



Fuzzy Логический вывод


Использование max-min отношений Заде , как показал опыт , дают точные результаты.

Последовательность:
1. Очистить выходной вектор Y [ ].

2. Взять первый элемент вектора X1 [ ].

3. Сравните их с каждым элементом вектора X2 [ ]. Меньшее значение записывается при каждом сравнении.

4. Среди участников находится максимальное значение , полученное на шаге 3.

5. Это максимальное значение затем добавляется к выходному элементу вектора, который определяется правилами Логического вывода.

6. Берется ледующий элемент вектора X1 [ ] и процесс с 3 до 6 повторяется.

Правила вывода приведены в таблице 1.

Табл.1 Правила нечеткой логики


dError (X2[ ])
NM NS ZE PS PM
Error (X1[ ]) NM PM PM PM PS ZE
NS PM PM PS ZE NS
ZE PM PS ZE NS NM
PS PS ZE NS NM NM

PM ZE NS NM NM NM


В данном примере выходной вектор Y [ ] является: Y [ ] = [0 ч, 30h, 3D0h, 0h, 0h]


Центроидный метод расчета дефаззификации или метод среднего


Результатом дефаззификации должно быть числовое значение, которое определяет коэффициент заполнения PWM сигнала, используемого для управления двигателем. Оно получается путем нахождения центроида точки функции, которая является результатом умножения выходной функции принадлежности и выходного вектора Y [ ]. Общая математическая формула, которая используется для получения точки центроида:



(1)


Y [ i ] являются i-м членом выходного вектора

multifact [ i ] является коэффициентом выходной функции принадлежности .


На рисунке 4 показано графическое представление выходной функции принадлежности , используемый в данном приложении с коэффициентами [-10Н, -8Н, 0h, 8Н, 10Н].






Рис.4 Выходная функция принадлежности


Используя, например выходной вектор Y [ ] = [0h, 30h, 3D0h, 0h, 0h], можно рассчитать следующие выходные значения дефаззификации:


(2)


Рис.5 Выходная функция принадлежности помноженная с вектором Y[ ]



Описание устройства на микроконтроллере

Микроконтроллер MSP430F149 используется в данноммприложении для управления двигателем . Он может быть легко заменен любой другой MSP430 микроконтроллер с доступными двумя таймерами Timer_A и Timer_B . На рисунке 6 показана схема MSP430 с тактовой частотой 8 МГц для обеспечения источника тактовых импульсов с высоким разрешением, которое используется для генерации ШИМ-регулирования и измерения скорости.

Универсальный серийный электродвигатель приводится в действие с помощью ШИМ-сигнала, генерируемого с использованием блока сравнения/ захвата Timer_B, управляется в режиме сравнения. Выходной сигнал MSP430 подается на драйвер двигателя выходного каскада. В этом примере, каскад двигателя питается от выпрямленного 230-V напряжения питающей сети.


Для обеспечения обратной связи в нечетком контуре логического управления используется оптический датчик. Этот датчик состоит из передатчик и приемника света. С помощью щелевого диска, который прикреплен к валу двигателя, генерируются 24 импульсов для каждого оборота вала двигателя . Фактическая частота вращения двигателя получается путем измерения времени между двумя последовательными импульсами с захватом блоком сравнения/захвата Timer_A , работающего в режиме захвата.

Для минимизации погрешности измерения, что имеет место в высоковольтном двигателе, используется 8-ми канальный фильтр скользящего среднего.








Рис.6 Схема устройства


После настройки микроконтроллера MSP430 часы, периферийные устройства настроены в требуемое состояние. Timer_A используется для определения фактической скорости двигателя. Передний фронт входа CCI0B (вывод порта P2.2) используется для запуска события захвата 0-м блоком сравнения/захвата таймера Timer_A. В соответствии функции ISR, считывается и обрабатывается точная временная метка Hardware- генератора . После прохождения этого значения через 8-канальный фильтр среднего скользящего, вновь рассчитанное значение скорости сохраняется в глобальной переменной CurrentSpeed.

Блок захвата / сравнения 1 сконфигурирован в режим сравнения и используется для обеспечения механизма тайм-аута для измерения скорости. Это необходимо для того, что в случае, когда двигатель не стоит на месте, захвата событий не будет генерироваться, а программное обеспечение не будеть неправильно считать, что двигатель все еще работает. Тем не менее, с реализацией этого тайм-аута, глобальная переменная CurrentSpeed все еще обновляется и алгоритм управления будет продолжать работать. Обратите внимание, что Timer_A работает в непрерывном режиме, чтобы избежать этого, любая программная задержка влияет на измерения. Блок 2 захвата / сравнения таймера Timer_B настроен на режим сравнения и используется для формирования ШИМ-сигнала. Timer_B работает в повышающем режиме и управляется источником 8MHz часов.С помощью регистра периода, установленного в 3999, эффективная выходная частота ШИМ 8MHz / (3999 + 1) = 2 кГц. Эта установка дает прекрасную детализацию для регулировки мощности двигателя, что приводит к более плавному управлению. Обратите внимание, что для нашего примера, выбор блока захвата / сравнения выбор таймеров Timer_A и Timer_B произвольный. Для более детальной информации обратитесь к [3].

Затем модуль (WDT) таймер MSP430 сторожевого конфигурируется, как интервальный таймер. Связанная с ним ISR функция вызывается 244 раз в секунду и пробуждает процессор из режима пониженного энергопотребления LPM0. Этот механизм обеспечивает интервал времени между каждым циклом управления.

После того, как периферия сконфигурирована,вводится фактический контур управления. Сразу при входе,активизируется Режим 0 с низким энергопотреблением, тем самым выключая процессор и останавливая выполнения программы на время ожидания. Выход из спящего режима вызывается WDT ISR.

При пробуждении микроконтроллера, ошибки абсолютного и дифференциального контура управления'Error' и 'dError' рассчитываются на основе заданной скорости (переменной SetSpeed), текущей скорости (переменная CurrentSpeed) и предыдущего значения ошибки (Переменная LastError). Эти значения ошибок затем преобразуются в нечеткие векторы X1 [ ] и Х2 [ ] с помощью функции фаззификации (). После того, как применяются фаззификация и нечеткие правила вывода , нечеткий вывод вектор Y [ ] генерируется посредством вызова функции FuzzyInference (). Этот выходной вектор затем преобразуется обратно в одно выходное значение контура управления с помощью вызова дефаззификации () и добавляется к текущему циклу ШИМ. Таким образом, контур управления замыкается. Обратите внимание, что два определения PWM_Min и PWM_Max используются для ограничения дежурного цикла двигателя и может потребоваться корректировка в зависимости от приложения и нагрузки.

Для обсуждения используемых алгоритмов нечеткой логики, пожалуйста, обратитесь к разделу 1. На Рисунке 7, Рисунке 8 показан пример запуска двигателя с помощью испытательной установки, которая была использована для разработки и проверки описанного в данной статье алгоритма. Скорость двигателя устанавливается на 50 rpsec, на прилагаемых графиках показан запуск двигателя без и с механической нагрузкой.





Рис.7. Запуск двигателя без нагрузки






Рис.8 Запуск двигателя с нагрузкой



Программа на языке Си для среды разработки IAR



  1 //------------------------------------------------------------------------------
  2 // MSP430F14x Fuzzy Logic Motor Control Demo
  3 //
  4 // Описание: Программа управляет двигателем с помощью алгоритма нечеткой логики Fuzzy logic
  5 // Фактическая частота вращения определяется измерением времени между переходами от 
  6 // оптического датчика
  7 // Заданная скорость записывается в переменную SetSpeed.
  8 //
  9 //             MSP430F14x
 10 //          +---------------+
 11 //          |                |
 12 //          |           P2.2|<--- Оптический энкодер, 24 импульса на оборот
 13 //          |                |
 14 //          |           P4.2|---> PWM широтно-импульсная модуляция, выходной каскад привода
 15 //          |                |
 16 //          | XIN/XOUT|<--- 8MHz crystal   генератор тактовой частоты микроконтроллера
 17 //          |                |
 18 //          +---------------+
 19 //
 20 // Andreas Dannenberg
 21 // Texas Instruments Inc.
 22 // January 2005
 23 // Built with IAR Embedded Workbench Version: 3.21A
 24 //
 25 // Courtesy of Dr. Odry Pйter, Divйki Szabolcs, Csasznyi Andor, Bъrбny Nбndor
 26 //------------------------------------------------------------------------------
 27 // THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
 28 // REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
 29 // INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 30 // FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
 31 // COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
 32 // TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
 33 // POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
 34 // INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
 35 // YOUR USE OF THE PROGRAM.
 36 //
 37 // IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
 38 // CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
 39 // THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
 40 // OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
 41 // OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
 42 // EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
 43 // REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
 44 // OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
 45 // USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
 46 // AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
 47 // YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
 48 // (U.S.$500).
 49 //
 50 // Unless otherwise stated, the Program written and copyrighted
 51 // by Texas Instruments is distributed as "freeware".  You may,
 52 // only under TI's copyright in the Program, use and modify the
 53 // Program without any charge or restriction.  You may
 54 // distribute to third parties, provided that you transfer a
 55 // copy of this license to the third party and the third party
 56 // agrees to these terms by its first use of the Program. You
 57 // must reproduce the copyright notice and any other legend of
 58 // ownership on each copy or partial copy, of the Program.
 59 //
 60 // You acknowledge and agree that the Program contains
 61 // copyrighted material, trade secrets and other TI proprietary
 62 // information and is protected by copyright laws,
 63 // international copyright treaties, and trade secret laws, as
 64 // well as other intellectual property laws.  To protect TI's
 65 // rights in the Program, you agree not to decompile, reverse
 66 // engineer, disassemble or otherwise translate any object code
 67 // versions of the Program to a human-readable form.  You agree
 68 // that in no event will you alter, remove or destroy any
 69 // copyright notice included in the Program.  TI reserves all
 70 // rights not specifically granted under this license. Except
 71 // as specifically provided herein, nothing in this agreement
 72 // shall be construed as conferring by implication, estoppel,
 73 // or otherwise, upon you, any license or other right under any
 74 // TI patents, copyrights or trade secrets.
 75 //
 76 // You may not use the Program in non-TI devices.
 77 //------------------------------------------------------------------------------
 78 
 79 #include "msp430x14x.h"
 80 
 81 #define PWM_Period      3999                    // 8MHz / 4000 = 2kHz
 82 #define PWM_Max         1199                    // Максимально используемый коэффициент заполнения
 83 #define PWM_Min         149                     // Min duty factor used
 84 
 85 #define MIN_SPEED       10000                   // Минимальная измеренная скорость
 86 
 87 int Array[700];                                 // Debug буфер
 88 int pArray = 0;
 89 
 90 unsigned int SetSpeed = 1667;                   // 1667 equal 50rpsec
 91                                                 // SetSpeed = f_Timer / (RevPerSec * 24)
 92                                                 // with f_Timer = 2MHz
 93 
 94 unsigned int LastTACCR;                         // Измерение скоростиt vars
 95 unsigned int CurrentSpeed = MIN_SPEED;
 96 unsigned long SpeedMemSum = 8 * (unsigned long)MIN_SPEED;
 97 unsigned int pSpeedMem = 0;
 98 unsigned int SpeedMem[8] =
 99 {
100   MIN_SPEED, MIN_SPEED, MIN_SPEED, MIN_SPEED,
101   MIN_SPEED, MIN_SPEED, MIN_SPEED, MIN_SPEED
102 };
103 
104 long Error;                                     // Control algorithm vars
105 long dError;
106 long LastError;
107 long PWMValue;
108 
109 int X1[5];                                      // Fuzzy нечеткие управляющие переменные
110 int X2[5];
111 int Y[5];
112 int Output;
113 
114 #define NM          0                           // negative medium
115 #define NS          1                           // negative small
116 #define ZE          2                           // zero equal
117 #define PS          3                           // positive small
118 #define PM          4                           // positive medium
119 
120 const unsigned char InferenceTable[5][5] =
121 {
122   { PM, PM, PM, PS, ZE },
123   { PM, PM, PS, ZE, NS },
124   { PM, PS, ZE, NS, NM },
125   { PS, ZE, NS, NM, NM },
126   { ZE, NS, NM, NM, NM }
127 };
128 
129 const signed char OutputFunc[5] =
130 {
131   -0x10, -0x08, 0, 0x08, 0x10
132 };
133 
134 // Function prototypes
135 void InitSystem(void);
136 void Fuzzification(int Value, int *Data);
137 void FuzzyInference(int *Error, int *dError, int *Y);
138 int Defuzzification(int *Y);
139 __interrupt void WDT_ISR(void);
140 __interrupt void TimerA0_ISR(void);
141 __interrupt void TimerA1_ISR(void);
142 
143 void main(void)
144 {
145   volatile unsigned int i;
146 
147   InitSystem();
148 
149   while (1)
150   {
151     __bis_SR_register(LPM0_bits);               // Enter LPM, wait for start of
152                                                 // next control cycle
153 
154     // If Error > 0 then motor is to fast
155     // If Error < 0 then motor is to slow
156 
157     LastError = Error;
158 
159     __disable_interrupt();                      // Protect following statements
160     Error = (long)SetSpeed - CurrentSpeed;      // Calc absolute error
161 
162     if (pArray < sizeof Array/sizeof Array[0])  // Store some values for debug
163       Array[pArray++] = CurrentSpeed;
164 
165     __enable_interrupt();
166 
167     Error <<= 3;                                // Multiply by 8
168 
169     dError = Error - LastError;                 // Calc differential error
170     dError <<= 5;                               // Multiply by 32
171 
172     // Ensure error is within Fuzzy boundaries
173     if (Error > 0xc00)                          // Motor too fast?
174     {
175       TBCCR2 = PWM_Min;                         // Set PWM to minimum
176       continue;                                 // Skip over control algorithm
177     }
178 
179     if (Error < -0xc00)                         // Motor too slow?
180     {
181       TBCCR2 = PWM_Max;                         // Set PWM to maximum
182       continue;                                 // Skip over control algorithm
183     }
184 
185     Fuzzification(Error, X1);                   // Transform absolute error
186     Fuzzification(dError, X2);                  // Transform differential error
187     FuzzyInference(X1, X2, Y);                  // Apply Fuzzy rule table
188     Output = Defuzzification(Y);                // Obtain scalar result
189 
190     PWMValue = TBCCR2 + Output;
191     if (PWMValue < PWM_Min) PWMValue = PWM_Min; // Limit output value
192     if (PWMValue > PWM_Max) PWMValue = PWM_Max;
193     TBCCR2 = PWMValue;                          // Assign new PWM duty cycle
194   }
195 }
196 //------------------------------------------------------------------------------
197 // Function converts the discrete input value 'Value' into the 5-element
198 // Fuzzy vector Data[ ].
199 //------------------------------------------------------------------------------
200 void Fuzzification(int Value, int *Data)
201 {
202   int i;
203 
204   for (i = 0; i < 5; i++)
205     Data[i] = 0;
206 
207   if (Value < -0x800)
208     Data[NM] = 0x400;
209   else if (Value < -0x400)
210   {
211     Data[NM] = 0x400 - (Value + 0x800);
212     Data[NS] = Value + 0x800;
213   }
214   else if (Value < 0)
215   {
216     Data[NS] = 0x400 - (Value + 0x400);
217     Data[ZE] = Value + 0x400;
218   }
219   else if (Value < 0x400)
220   {
221     Data[ZE] = 0x400 - Value;
222     Data[PS] = Value;
223   }
224   else if (Value < 0x800)
225   {
226     Data[PS] = 0x400 - (Value - 0x400);
227     Data[PM] = Value - 0x400;
228   }
229   else
230     Data[PM] = 0x400;
231 }
232 //------------------------------------------------------------------------------
233 // Function applies the Fuzzy control interference rule table InferenceTable[ ][ ]
234 // to the two input arrays X1[ ] and X2[ ] to generate the output vector Y[ ].
235 //------------------------------------------------------------------------------
236 void FuzzyInference(int *X1, int *X2, int *Y)
237 {
238   int min[5];
239   int max;
240   int maxpos;
241   int i, j;
242 
243   for (i = 0; i < 5; i++)                       // Clear output vector Y[ ]
244     Y[i] = 0;
245 
246   for (i = 0; i < 5; i++)                       // Loop through X1[ ]
247   {
248     for (j = 0; j < 5; j++)                     // Loop through X2[ ]
249       if (X1[i] < X2[j])                        // Determine smaller value,
250         min[j] = X1[i];                         // store into min[ ]
251       else
252         min[j] = X2[j];
253 
254     max = min[0];                               // Find maximum in min[ ]
255     maxpos = 0;
256     for (j = 1; j < 5; j++)
257       if (max < min[j])
258       {
259         max = min[j];                           // Store maximum
260         maxpos = j;                             // Store position of maximum
261       }
262 
263     if (max > Y[InferenceTable[i][maxpos]])     // Apply inference table
264       Y[InferenceTable[i][maxpos]] += max;
265 
266     if (Y[InferenceTable[i][maxpos]] > 0x400)   // Limit output vector elements
267       Y[InferenceTable[i][maxpos]] = 0x400;
268   }
269 }
270 //------------------------------------------------------------------------------
271 // Function transforms the Fuzzy vector Y[ ] to a discrete value using the
272 // center of gravity method.
273 //------------------------------------------------------------------------------
274 int Defuzzification(int *Y)
275 {
276   int i;
277   int ReturnVal = 0;
278   int SumY = 0;
279 
280   for (i = 0; i < 5; i++)
281   {
282     SumY += Y[i];
283     ReturnVal += Y[i] * OutputFunc[i];
284   }
285 
286   return ((long)ReturnVal << 2) / SumY;         // Scale result by 4
287 }
288 //------------------------------------------------------------------------------
289 // MSP430-specific initialization of clock system and timer modules
290 //------------------------------------------------------------------------------
291 void InitSystem(void)
292 {
293   volatile unsigned int i;
294 
295   WDTCTL = WDTPW + WDTHOLD;                     // Hold WDT
296 
297   // Setup Clock System
298   BCSCTL1 |= XTS;                               // ACLK=LFXT1=HF XTAL
299 
300   do {
301     IFG1 &= ~OFIFG;                             // Clear OSCFault flag
302     for (i = 0xFF; i > 0; i--);                 // Time for flag to set
303   } while (IFG1 & OFIFG);                       // OSCFault flag still set?
304 
305   BCSCTL2 |= SELM_3;                            // MCLK=LFXT1 (safe)
306 
307   // Setup Ports
308   P2SEL = 0x04;                                 // Assign P2.2 to Timer_A.CCI0B
309   P4SEL = 0x04;                                 // Assign P4.2 to Timer_B.OUT2
310   P4DIR = 0x04;                                 // P4.2 output
311 
312   // Setup Timer_A for speed measurement
313   TACCR1 = MIN_SPEED;                           // Set minimum speed that is read out
314   TACCTL0 = CM_1 + CCIS_1 + SCS + CAP + CCIE;   // Capture rising edge of CCI0B, interrupt
315   TACCTL1 = CCIE;                               // Compare mode, interrupt on EQU1
316   TACTL = TASSEL_1 + ID_2 + MC_2;               // Use ACLK/4=2MHz, start in continuos mode
317 
318   // Setup Timer_B for PWM generation
319   TBCCR0 = PWM_Period;                          // PWM Period
320   TBCCTL2 = OUTMOD_7 + CLLD0;                   // Set OUT2 on EQU0, reset on EQU1,
321                                                 // sync latch load with EQU0
322   TBCTL = TBSSEL_1 + MC_1;                      // Use ACLK, start in up-mode
323 
324   // Setup WDT for periodic interrupt
325   WDTCTL = WDTPW + WDTTMSEL + WDTSSEL;          // Intervall timer, 8MHz/32768=244Hz
326   IE1 |= WDTIE;
327 
328   __enable_interrupt();
329 }
330 //------------------------------------------------------------------------------
331 // The Watchdog-timer ISR is used to periodically wake-up from low-power mode
332 // LPM0 to execute the Fuzzy control loop.
333 //------------------------------------------------------------------------------
334 #pragma vector = WDT_VECTOR
335 __interrupt void WDT_ISR(void)
336 {
337   __bic_SR_register_on_exit(LPM0_bits);         // Wake up from LPM
338 }
339 //------------------------------------------------------------------------------
340 // The Timer_A CCR0 ISR is called on each TACCR0 capture event to obtain
341 // the time stamp of the input signal transition. An 8-tap moving average
342 // filter is used to minimize measurement error.
343 //------------------------------------------------------------------------------
344 #pragma vector = TIMERA0_VECTOR
345 __interrupt void TimerA0_ISR(void)
346 {
347   SpeedMemSum -= SpeedMem[pSpeedMem];           // Remove oldest value
348   SpeedMem[pSpeedMem] = (unsigned int)(TACCR0 - LastTACCR);  // Replace with current
349   SpeedMemSum += SpeedMem[pSpeedMem++];         // Update running sum
350   CurrentSpeed = SpeedMemSum >> 3;              // Calc speed by div 8
351   pSpeedMem &= 0x07;                            // Adjust circular pointer
352 
353   LastTACCR = TACCR0;
354   TACCR1 = LastTACCR + MIN_SPEED;               // Set timeout for minimum speed
355 }                                               // to be read out
356 //------------------------------------------------------------------------------
357 // The Timer_A CCR1 ISR is called on TACCR1 compare events, which are generated
358 // when no input signal change is detected within 'MIN_SPEED' clock ticks after
359 // the last TACCR0 event. This provides a timeout function to update the speed
360 // variables in the case the motor gets halted.
361 //------------------------------------------------------------------------------
362 #pragma vector = TIMERA1_VECTOR
363 __interrupt void TimerA1_ISR(void)
364 {
365   switch (TAIV)
366   {
367     case 0x02 :                                 // TACCR1 CCIFG
368       SpeedMemSum -= SpeedMem[pSpeedMem];       // Remove oldest value
369       SpeedMem[pSpeedMem] = (unsigned int)(TACCR1 - LastTACCR);  // Replace with current
370       SpeedMemSum += SpeedMem[pSpeedMem++];     // Update running sum
371       CurrentSpeed = SpeedMemSum >> 3;          // Calc speed by div 8
372       pSpeedMem &= 0x07;                        // Adjust circular pointer
373 
374       LastTACCR = TACCR1;
375       TACCR1 = LastTACCR + MIN_SPEED;           // Set timeout for minimum speed
376       break;                                    // to be read out
377   }
378 }
379 


Литература


1. Fuzzy Logic: An Overview of the Latest Control Methodology (SPRA028)
2. MSP430x13x, MSP430x14x Mixed Signal Microcontroller Data Sheet (SLAS272)
3. MSP430x1xx Family User’s Guide (SLAU049)
Написать:
22:47
2067
19:54
Интересная статейка, судя по модели контроллера, довольно давно программа писалась.
Но портировать на другие модели действительно не сложно.
Интересно, а почему сейчас как-то подзабылась эта тема?
Или уже не актуально?
В 90-х как то все спохватились выпускать специализированные контроллеры,
а сейчас чего-то поутихла эта тема.