Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
146 lines (117 sloc) 8.08 KB
// pid.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdint.h>
/*
position = ReadPlantADC();
drive = UpdatePID(&plantPID, plantCommand - position, position);
DrivePlantDAC(drive);
*/
/*
http://roboforum.ru/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%B2%D0%BE%D0%B4_%D1%81%D1%82%D0%B0%D1%82%D1%8C%D0%B8_%22%D0%9F%D1%80%D0%BE%D1%81%D1%82%D0%BE_%D0%BE_%D0%9F%D0%98%D0%94-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0%D1%85%22
Настройка ПИД-регулятора
ПИД-регуляторы замечательны тем, что для их хорошей настройки не требуется отличного
понимания формальной теории управления системами. При этом они позволяют решить около
90% всех задач управления простыми системами замкнутого цикла.
Если можете, подцепите ваш контроллер к тестовому оборудованию или напишите отладочный
код, чтобы можно было видеть, что происходит внутри, если возможно - соедините контроллер
с ПК по последовательному порту и выведите отладочные графики в какой-нибудь программе,
например в Excel. Кроме этого вам потребуется какой-то способ ступенько-образного задания
управляюшего сигнала. Вполне может подойти опять же отладочный код, который будет брать
управляющий сигнал скажем с последовательного порта. Как только вы закончили все
приготовления установите все коэффициенты в 0. Если вы полагаете, что вам не нужно будет
дифференциальную компоненту (как в случае с двигателем или термосистемой), пропустите
следующую секцию и сразу приступайте к настройке пропорциональной компоненты. Иначе начинаем
с настройки коэффициента дифференциального управления.
Настройка дифференциальной компоненты
Перед настройкой дифференциального управления выставьте коэффициент пропорционального
управления в какое-нибудь небольшое значение (1 или немного меньше). Посмотрите как себя
ведёт система. Если она колеблется при нулевом коэффициенте дифференциальной компоненты,
тогда это можно исправить увеличением этого коэффициента. При постепенном увеличении
смотрите как себя ведёт система, увеличиваейте коэффициент пока не увидите возникающие
из-за малых шумов системы ошибочные колебания и вылеты по этой же причине за целевые
значения. Обратите внимение, что колебания от слишком большого коэффициента значительно
быстрее, чем колебания от недостаточного коэффициента. Я стараюсь устанавливать коэффициент
в половину или четверть от того, при котором начинаются колебания от слишком большой
его величины. Убедитесь что при этом управляющий сигнал выглядит адекватным. В этот момент
система реагирует на управляющее воздействие очень лениво, так что самое время настроить
пропорциональный и интегральный коэффициенты.
Настройка пропорциональной компоненты
Если вы еще не установили коэффициент пропорциональной компоненты, назначьте ему некоторое
стартовое значение (от 1 до 100). Ваша управляемая система либо покажет ужасающе медленную
реакцию на команды, либо начнет колебания. Если вы видите колебания - уменьшайте коэффициент
в 10 раз, пока эти колебания не прекратятся. Если вы не наблюдаете колебания, увеличивайте
коэффициент в 10 раз пока не начнутся колебания или значительные "перелёты" через целевое
положение. Теперь уже с коэффициентом 2 найдите такой коэффициент, что он всё еще не вызывает
колебаний или "перелётов", а умноженный на 2 уже вызывает, теперь можно немного его уменьшить
пока вам не понравится действие системы.
Настройка интегральной компоненты
И наконец мы можем приступить к настройке коэффициента интегральной компоненты, начальные
значения коэффициента рекомендуется брать от 0.0001 до 0.01. Ищем нужное нам значение так же
как с пропорциональным коэффициентом, так же отступая немного назад, чтобы гарантированно
не получить колебания от слишком большого коэффициента.
*/
struct SPid {
long dState; // Last position input
long iState; // Integrator state
long iMax, iMin;
// 1/65536 == 0,000015
// 1/8192 == 0,00012
// 1/64 == 0,015625
// Maximum and minimum allowable integrator state
long iGain, // integral gain (0.0001 .. 0.01) ( * 1-64 / 8192)
pGain, // proportional gain (1 .. 100)
dGain; // derivative gain (<= 1.0) ( * 1-256 / 256)
SPid():
iGain(long(0.9*65536)), pGain(long(0.25*65536)), dGain(long(0.005*65536)) {
dState = 0;
iState = 0;
iMin = 0;
iMax = 255;
}
long UpdatePID(long error, long position);
};
long SPid::UpdatePID(long error, long position) {
iState += error; // calculate the integral state with appropriate limiting
if (iState > iMax)
iState = iMax;
else if (iState < iMin)
iState = iMin;
long res = pGain * error + // calculate the proportional term
iGain * iState - // calculate the integral term
dGain * (position - dState); // сумматор 2
res /= 65536;
dState = position;
return res;
}
class Motor {
public:
int m_Speed;
double m_Load;
Motor(double load): m_Speed(0), m_Load(load) {}
void Set(int pwm) {
m_Speed = int(pwm*m_Load);
}
int Get() {
return m_Speed;
}
};
const long req_speed = 200; // моторчик должен разогнаться до 255 единиц скорости
void test(double load) {
SPid pid;
Motor m(load);
for (int i = 0; i < 30; i++) {
int s = m.Get();
long act = pid.UpdatePID(
req_speed - s, // сумматор 1
s); // AVR PWM should work in range 0 - 255
m.Set(act);
printf("%4ld", s);
}
printf("\n");
}
int main() {
test(0.9);
test(1.0);
return 0;
}