roboforum.ru

Технический форум по робототехнике.

ПИД на AVR (энкодер + шим)

ПИД на AVR (энкодер + шим)

Levin88 » 29 май 2011, 02:37

Добрый вечер.
Пытаюсь сделать ПИД-регулятор с обратной связью по скорости
для мотора с квадратурным энкодером (300 имп/об)
на Atmega8535 в Proteus.

Измерение скорости провожу отсчетом числа импульсов
с энкодера таймером T0, за промежуток 0,05 с,
сформированный по прерыванию от T1,
в этом же прерывании прозвожу вычисление ПИД и выдачу сигнала на OCR2

Основная часть программы:

// требуемая скорость
#define Target 100
// коэффициент пропорционального усиления
#define Kp 5
// коэффициент интегрального усиления
#define Ki 0.3
// коэффициент дифференциального усиления
#define Kd 5
// максимальная сумма ошибок
#define MaxIntegral 1000

volatile signed int Error; // отклонение измеренной величины от заданной
volatile signed int PrevValue; // предыдущее значение измерения
volatile signed int P_Term; // пропорциональный компонент
volatile signed int I_Term; // интегральный компонент
volatile signed int D_Term; // дифференциальный компонент
volatile signed int Out; // управляющее воздействие
volatile signed int Integral; // сумма ошибок

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
Perepol++;
}

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Reinitialize Timer1 value
TCNT1H=0xF78F >> 8;
TCNT1L=0xF78F & 0xff;
// Place your code here
VMH=Perepol;
VML=TCNT0;
Error = Target - TCNT0;
P_Term = Kp * Error;

if (Integral > MaxIntegral) {Integral = MaxIntegral;}
else if (Integral < - MaxIntegral) {Integral = - MaxIntegral;}
else Integral += Error;

I_Term = Ki * Integral;
D_Term = Kd * (PrevValue - TCNT0);
PrevValue = TCNT0;
Out = P_Term + I_Term + D_Term;

if(Out > 0xFF) { OCR2 = 0xFE; }
else if(Out < 0) { OCR2 = 0;}
else OCR2 = Out;
pwm=OCR2;
TCNT0=0;
Perepol=0;
}

В принципе кое-как работает,но слишком медленно стабилизируется и есть колебания.
Возможно стоит производить измерения скорости между импульсами с энкодера.
Подскажите как лучше реализовать измерение скорости и регулирование в данном случае.
Если у кого есть подобный проект в Proteus с исходниками, то не могли бы вы его выложить для изучения на примере.

Re: ПИД на AVR (энкодер + шим)

noonv » 29 май 2011, 09:22

а менять коэффициенты ПИД пробовали? :)

Re: ПИД на AVR (энкодер + шим)

avr123.nm.ru » 29 май 2011, 11:05

Levin88 писал(а):Добрый вечер.
Пытаюсь сделать ПИД-регулятор с обратной связью по скорости
для мотора с квадратурным энкодером (300 имп/об)
на Atmega8535 в Proteus.


Смотрите пример PROTEUS AN699

Re: ПИД на AVR (энкодер + шим)

Levin88 » 29 май 2011, 16:57

Пробовал менять, но пока не получил приемлемых результатов.
Сейчас пытаюсь посчитать коэффициенты по методу Циглера-Николса.

Пытался разобраться в программе для AN696, но пока не осилил + c PIC-ми совсем не знаком
AN699 не встречал. Где он находится? (samples->...)

Re: ПИД на AVR (энкодер + шим)

Michael_K » 29 май 2011, 18:32

0. И - уберите совсем.

1. Подберите П, чтобы держал скорость как-то (пусть с колебаниями)

2. Д - увеличивайте, чтобы пропали колебания. П - потихоньку уменьшайте

Re: ПИД на AVR (энкодер + шим)

Duhas » 29 май 2011, 19:30

ммм, на скорость обычно ПИ регулятор ставят вроде )

Re: ПИД на AVR (энкодер + шим)

Michael_K » 29 май 2011, 21:45

ну как хотите :)

Re: ПИД на AVR (энкодер + шим)

Duhas » 30 май 2011, 10:52

ну зависит от того что там на движке будет )) точнее от инерционности... ПИ разгонит быстрее


Rambler\'s Top100 Mail.ru counter