|
|
  |
ПИД регулятор на ARM |
|
|
|
Jul 20 2008, 18:09
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Цитата(_Pasha @ Jul 20 2008, 21:01)  +1000  Люди,ау! Добавьте признак, что если имеется ограничение по выходу, то считаем интегральный терм. Для уверенности лучше микрочиповские аппликухи перечитать, раз на атмеловских такаядеталь проскочила. Какая деталь проскочила? Есть там в алгоритме ограничение интегрального терма (нижние и верхние границы регулировки)! Смотри хотя бы текст программы.
|
|
|
|
|
Jul 20 2008, 18:40
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Dir @ Jul 20 2008, 21:09)  Какая деталь проскочила? Есть там в алгоритме ограничение интегрального терма (нижние и верхние границы регулировки)! Смотри хотя бы текст программы. Возвращаемся. Я про это: Цитата(Dir @ Jul 20 2008, 19:55)  И вот что от него остается для ARM: С исправлениями Код typedef struct { float fKp; float fKi; float fKd; float fLastProcessValue; float fLastOutput; // добавлено: последний ПИД float fSumError; float fMaxPID; float fMinPID; } PID_DATA; /********************************************************/ WORD ContrPID(float fSetPoint, float fProcessValue, PID_DATA *pid) { float fError, fPterm, fDterm, fIterm, fRet, fsError; fError = fSetPoint - fProcessValue; // Вычисление P-терма fPterm = pid->fKp * fError; // Вычисление D-терма fDterm = pid->fKd * (fProcessValue - pid->fLastProcessValue); pid->fLastProcessValue = fProcessValue;
// Вычисление I-терма /* накапливаем сумму для интегрального терма, если выход был в насыщении то считаем его, иначе сумма курит в сторонке и отражает медленные процессы, т.е. в конце концов ошибка изменит свой знак и скомпенсирует все, что складывалось до того */
pid->fSumError += fError;
if((pid->fLastOutput > pid->fMaxPID)||(pid->fLastOutput < pid->fMinPID )) { fIterm = pid->fKi * pid->fSumError; // посчитали } // выход fRet = fPterm + fDterm + fIterm + pid->fMinPID; // тоже непонятно, потому что должен быть pid->fOffset pid->fLastOutput = fRet; // запомнили выход для анализа его в следующий раз // if (fRet > pid->fMaxPID) return (WORD)(pid->fMaxPID); else if (fRet < pid->fMinPID) return (WORD)(pid->fMinPID); pid->fSumError = fsError; return (WORD)fRet; } Ясное дело, коряво немного, но с минимумом изменений. Кому надо, тот флаг Saturated добавит вместо плавучки  Исправил код еще раз.
|
|
|
|
|
Jul 20 2008, 19:52
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Пока не рабирал, т.к. воскресенье и думать совсем лень, но вот это не понял сразу Цитата(_Pasha @ Jul 20 2008, 21:40)  /* накапливаем сумму для интегрального терма, если выход был в насыщении то считаем его, иначе сумма курит в сторонке и отражает медленные процессы, т.е. в конце концов ошибка изменит свой знак и скомпенсирует все, что складывалось до того */ Т.е. почему сумма изменит свой знак?
|
|
|
|
|
Jul 20 2008, 20:28
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Повторю, что сказала Таня, но своими словами. Выход регулятора имеет уровни ограничения - это понятно. Пока выход не ограничивается, нам интегральная часть не нужна Все-таки в коде ошибка, правильно так Код if((pid->fLastOutput > pid->fMaxPID)||(pid->fLastOutput < pid->fMinPID )) { fIterm = pid->fKi * pid->fSumError; // посчитали } else { fIterm = 0; } Как только выход в насыщении (ограничении), мы вспоминаем о сумме и интегральном терме. Получаеццо, выход в насыщении, а ошибка все равно есть. Девушко: Доктор, что мне делать, у меня прыщи и маленькая грудь... Доктор: Прыщи, маленькая грудь... Маленькая грудь, прыщи - это ж замкнутый круг какой-то... И вот наступает время, когда замкнутый круг наконец-то порвался, и ошибка (по модулю) начинает снижаться. Если же этого не происходит - то чума на голову такого регулятора. А выход все равно в ограничении. А потом наступает перерегулирование, и знак ошибки ужЕ поменялся, и у нас наконец-то выход не в ограничении. Забыли про интегральный терм. И т.д.
|
|
|
|
|
Jul 20 2008, 22:12
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Дневная жара спала и наконец-то возратилась способность хоть как то соображать  Не оставляет ощущение, что мы говорим о разных регуляторах. Или совсем не понимаем друг друга. На эту мысль наводят слова: Цитата(_Pasha @ Jul 20 2008, 23:28)  Повторю, что сказала Таня, но своими словами. Выход регулятора имеет уровни ограничения - это понятно. Пока выход не ограничивается, нам интегральная часть не нужна Все-таки в коде ошибка, правильно так Код if((pid->fLastOutput > pid->fMaxPID)||(pid->fLastOutput < pid->fMinPID )) { fIterm = pid->fKi * pid->fSumError; // посчитали } else { fIterm = 0; } Недаром pid->fMaxPID восприняты как регулируемая величина. А на самом деле это регулирующее воздействие. Причем вместо выхода сумматора сравнение ведется с регулируемой величиной (хотя не возражаю, иногда работают и с выходом). Поэтому приведу расшифровку принятых обозначений. Структура PID_DATA: fKp, fKi, fKd - коэффициенты регулятора fLastProcessValue - последнее значение регулируемой величины fSumError - понятно fMinPID...fMaxPID - допустимый диапазон задания регулирующих воздействий Переменные функции ContrPID: fSetPoint - желаемое значение регулируемой величины fProcessValue - текущее значение регулируемой величины PID-регулятор классический. Т.е. все термы работают одновременно, а не так, что I-терм нужен только в режиме насыщения. Отсюда понятна формула, что регулирующее воздействие fRet равно сумме всех термов, которые считаем от 0, плюс pid->fMinPID - начальное регулирующее воздействие. fRet = fPterm + fDterm + fIterm + pid->fMinPID В случае достижения регулирующего воздействия максимальной величины fMaxPID или минимальной величины fMinPID происходит его ограничение на этом уровне. Поэтому ошибка регулирования в дальнейшем в случае приближения регулируемой величины к желаемому значению должна уменьшаться. ... И вот теперь, когда расставлены дефиниции, можно поговорить и о предмете Жду замечаний и возражений
|
|
|
|
|
Jul 20 2008, 22:46
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Dir @ Jul 21 2008, 01:12)  Структура PID_DATA: fLastOutput - добавил от себя для реализации порожденного Татьяной замечания. Цитата PID-регулятор классический. Т.е. все термы работают одновременно, а не так, что I-терм нужен только в режиме насыщения. Вы ж понимаете, что они оба классические? Только имхо второй вариант имеет много больше применений. Ну да ладно. Пусть еще кто-нить рассудит А вот про то, что с fSumError в исходном варианте было неправильно, я думаю, Вы возражать не будете
|
|
|
|
|
Jul 21 2008, 05:02
|
Участник

Группа: Свой
Сообщений: 45
Регистрация: 7-11-05
Пользователь №: 10 537

|
Некоторые соображения по поводу ограничения интеграла... Код typedef struct { float fKp; float fKi; float fKd; float fLastProcessValue; float fI_term; float fMaxPID; float fMinPID; } PID_DATA; /********************************************************/ WORD ContrPID(float fSetPoint, float fProcessValue, PID_DATA *pid) { float fError, fPterm, fDterm, fIterm, fRet; fError = fSetPoint - fProcessValue; // Вычисление P-терма fPterm = pid->fKp * fError; // Вычисление D-терма fDterm = pid->fKd * (fProcessValue - pid->fLastProcessValue); pid->fLastProcessValue = fProcessValue;
// Вычисление I-терма fIterm = pid->fI_term + pid->fKi * fError;
// выход fRet = fPterm + fDterm + fIterm + pid->fMinPID;
if(fRet > pid->fMaxPID) { fRet = pid->fMaxPID; } if(fRet < pid->fMinPID ) { fRet = pid->fMinPID; } // Ограничение интеграла pid->fI_term = fRet - fPterm - fDterm - pid->fMinPID;
return (WORD)fRet; }
|
|
|
|
|
Jul 21 2008, 05:17
|

Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830

|
Цитата(_Pasha @ Jul 21 2008, 01:46)  fLastOutput - добавил от себя для реализации порожденного Татьяной замечания. Вы ж понимаете, что они оба классические? Только имхо второй вариант имеет много больше применений. Интересно услышать почему. Цитата(_Pasha @ Jul 21 2008, 01:46)  А вот про то, что с fSumError в исходном варианте было неправильно, я думаю, Вы возражать не будете Если речь про "мой" вариант, то буду. Нижняя и верхняя граница пределов задания управляющих воздействий (fMinPID, fMaxPID) выбирается с некоторым запасом меньше (больше) тех, что нужно для регулирования fProcessValue к уставкам fSetValue(min) и fSetValue(max). Это автоматом не позволяет интегральному терму бесконечно расти да еще и в направлении компенсации ошибки регулирования
|
|
|
|
|
Jul 21 2008, 06:18
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(маша @ Jul 21 2008, 08:02)  Некоторые соображения по поводу ограничения интеграла... Код // выход
//skipped
// Ограничение интеграла pid->fI_term = fRet - fPterm - fDterm - pid->fMinPID;
return (WORD)fRet; } Зачем в плавучке ограничение интеграла? Цитата(Dir @ Jul 21 2008, 08:17)  Если речь про "мой" вариант, то буду. Ну нельзя же так отжигать, право слово... Там нету накапливающего суммирования pid->fSumError не участвует как приемник данных ни в одном выражении
|
|
|
|
|
Jul 21 2008, 07:11
|
Гуру
     
Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883

|
Цитата(Dir @ Jul 20 2008, 21:53)  Не иллюзию создаст, а будет нормально работать. Вопрос в том стоит ли корпеть и вылизывать целочисленный алгоритм на AVR со множественными побочными явлениями и эффектами или за 5 минут наваять то же самое на ARM с плавучкой. А мне кажется, что иллюзии уже созданы. Проблема управления не есть задача программирования или электроники... Вот прикиньте - какова максимальная величина и минимальный квант управляющего воздействия. Разделим одно на другое и получим требуемую разрядность Интегрального Члена. Может разное получиться, но, обычно 16 бит хватит. Следует заметить, что в стационарном случае именно Интегральный член дает 95+ процентов управляющего воздействия (зависит от возмушений). Для Пропорционального и Дифференциального членов обычно хватает половинной разрядности. Но, пусть тоже будет 16 бит. Не вижу тут сложностей или потери быстродействия, - когда оно нужно - аналоговое управление. Для нестационарного случая - выход на стационарный режим - закон управления должен быть другой, если не хочется терять грубость (робастность).
|
|
|
|
|
Jul 21 2008, 12:00
|
Участник

Группа: Свой
Сообщений: 45
Регистрация: 7-11-05
Пользователь №: 10 537

|
Цитата(_Pasha @ Jul 21 2008, 10:18)  Зачем в плавучке ограничение интеграла? Ограничение интеграла - это алгоритмическое действие. И может применяться и в плавучке и в целых. В данном случае происходит не ограничение-замораживание интеграла, а его ограничение-коррекция.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|