В этом уроке
- Д-регулятор и за что он отвечает
- Настройка регулятора
- Управление машинкой с помощью ПД-регулятора
Видео версия урока
Общие сведения о ПД-регуляторе:
В прошлом уроке мы разобрались с работой П-регулятора.
Пропорциональный регулятор возвращает результат, который
пропорционален текущему значению ошибки.
Это достигается простым умножением текущей ошибки на коэффициент kP.
P = ОШИБКА * kP
П-регулятор указывает машине повернуть в сторону линии. Чем дальше линия от центра бампера, тем сильнее ошибка отличается от 0, и тем круче поворот машины.
Недостатком П-регулятора является то, что он не может работать на больших скоростях.
Для борьбы с указанным недостатком в одном регуляторе совмещают пропорциональную (П) и дифференциальную (Д) составляющую, — получается ПД-регулятор.
Дифференциальная составляющая (от лат. differentia – разность) — это разность между текущей и предыдущей ошибкой.
Дифференциальный регулятор возвращает результат, который
зависит от скорости изменения текущей ошибки.
Это достигается умножением разности ошибок на коэффициент kD.
D = (ОШИБКА – предыдущая ОШИБКА) * кD
Ошибки для Д-регулятора берутся через одинаковые интервалы времени, значит, разность между текущей и предыдущей ошибкой является скоростью изменения ошибки.
Чем выше скорость изменения ошибки, тем сильнее влияние Д-регулятора.
Д-регулятор выполняет сразу две задачи: он помогает П-регулятору справиться с резкими поворотами и превращает крутой въезд на линию в более пологий.
ПД-регулятор возвращает результат, который
является суммой пропорциональной и дифференциальной составляющих.
PD = P + D
Поведение составляющих ПД-регулятора:
Следующая картинка показывает, как ведут себя П-регулятор и Д-регулятор, если бампер движется по линии змейкой (МОТОРЫ НЕ ПОДКЛЮЧЕНЫ):
- Оранжевым цветом отражена текущая ошибка, возвращаемая бампером;
- Зелёным цветом отражено воздействие П-регулятора;
- Синим цветом отражено воздействие Д-регулятора.
(Картинка кликабельна)
Видно, что пик активности одного регулятора совпадает с бездействием другого.
Изначально, когда бампер возвращает ошибку 4.0 (значит, линия находится под крайним правым датчиком), П-регулятор указывает максимально круто повернуть вправо (в сторону линии). В это время Д-регулятор не проявляет никакой активности. По мере приближения линии к центру бампера (ошибка приближается к 0.0), П-регулятор снижает свою активность, выравнивая скорости моторов, а Д-регулятор до пересечения центра бампера с линией указывает повернуть влево, чтобы не переехать линию, а въехать на неё под пологим углом.
Если подключить моторы, то ПД-регулятор отработает следующим образом:
Код ПД-регулятора:
i = bum.getErrPID(); // Получаем текущую ошибку P = i * kP; // Определяем пропорциональную составляющую регулятора D = (i-j) * kD; // Определяем дифференциальную составляющую регулятора PD = P + D; // Получаем результат ПД-регулятора j = i; // Сохраняем текущую ошибку «i», как предыдущую «j», для следующего прохода по коду
Настройка ПД-регулятора:
- Настройка ПД-регулятора сводится к поиску коэффициентов для пропорциональной и дифференциальной составляющих;
- Назначение коэффициента П-регулятора kP описано в статье П-регулятор;
- Как уже было сказано ранее, задача Д-регулятора — получить разность ошибок и выдать число, на которое должны отличаться скорости колёс;
- Если Д-регулятор просто вернёт значение разности ошибок, этого может быть либо недостаточно для манёвра, либо слишком много;
- Поэтому Д-регулятор умножает разность ошибок на некий коэффициент kD.
Код Д-регулятора умещается в три строки: i = bum.getErrPID(); D = (i-j)*kD; j=i;,
где i — текущая ошибка, j — предыдущая ошибка, D — результат. - Подбор коэффициентов:
- Если kP=0, то ПД-регулятор будет работать как Д-регулятор;
- Если kD=0, то ПД-регулятор будет работать как П-регулятор;
- Сначала подбирается коэффициент kP для П-регулятора при kD=0. Значение kP должно быть таким, чтобы бампер машины не покидал линию трассы на всех её поворотах. Или был как можно ближе к линии на поворотах. При этом машина может "вилять" на прямых участках трассы — это нормально;
- Оставляем найденный kP и подбираем kD для дифференциальной составляющей;
- Постепенно увеличиваем kD. При этом машина будет всё меньше "вилять" на прямых участках трассы и лучше проходить крутые повороты;
- Слишком высокий коэффициент приведёт к тому, что машина начнёт "дрожать" на прямой линии. Это называется перерегулированием;
- Слишком низкий коэффициент не избавит от "виляний" машины на прямых участках трассы и не улучшит прохождение крутых поворотов. Это называется недорегулированием;
- Оптимальным является коэффициент, при котором бампер машины не покидает линию на всех поворотах трассы, при этом машина не "виляет" и не "дрожит" на прямых участках.
- Коэффициенты kP и kD являются константами, только если машина движется с одной скоростью.
Коэффициент регулятора определяет силу воздействия регулятора.
Чем больше коэффициент, тем сильнее меняется выходная величина.
Скетч для одной скорости:
Скорость колёс в скетче задаётся функцией setSpeed() в процентах.
Выберем скорость машины, равную 60%. Именно эту скорость мы и указываем обоим колёсам.
Предположим, что при kD = 0 и kP = 8 машина не покидает повороты трассы.
Предположим, что при kD = 14.4 и kP = 8 машина перестала "вилять" на прямых участках.
#include <Wire.h> // Подключаем библиотеку для работы с аппаратной шиной I2C #include <iarduino_I2C_Motor.h> // Подключаем библиотеку для работы с мотором I2C-flash #include <iarduino_I2C_Bumper.h> // Подключаем библиотеку для работы с бампером I2C-flash // iarduino_I2C_Motor mot_R (0x0A); // Объявляем объект mot_R для правого мотора, указав адрес модуля на шине I2C iarduino_I2C_Motor mot_L (0x0B); // Объявляем объект mot_L для правого мотора, указав адрес модуля на шине I2C iarduino_I2C_Bumper bum(0x0C); // Объявляем объект bum для работы с бампером I2C-flash, указав адрес модуля на шине I2C // float i, j; // Переменные для хранения ошибок float speed = 60; // Скорость машины в % float kP = 8; // Коэффициент пропорциональной составляющей float kD = 14.4; // Коэффициент дифференциальной составляющей // void setup(){ // mot_R.begin(); // Инициируем работу с левым мотором I2C-flash mot_L.begin(); // Инициируем работу с правым мотором I2C-flash bum.begin(); // Инициируем работу с бампером I2C-flash mot_R.setDirection(true); // Указываем правому мотору, что его вращение должно быть прямым (по часовой стрелке при положительных скоростях) mot_L.setDirection(false); // Указываем левому мотору, что его вращение должно быть обратным (против часовой стрелки при положительных скоростях) } // // void loop(){ // i = bum.getErrPID(); // Получаем текущую ошибку центрирования линии float P = i * kP; // Вычисляем пропорциональную составляющую float D = (i-j) * kD; // Вычисляем дифференциальную составляющую float PD = P+D; // Получаем значение от ПД-регулятора mot_R.setSpeed(speed - PD, MOT_PWM); // Устанавливаем скорость правого мотора mot_L.setSpeed(speed + PD, MOT_PWM); // Устанавливаем скорость левого мотора }
Дополнительное задание.
Попробуйте изменить коэффициент Д-регулятора kD и посмотрите на результат.
Скетч для диапазона скоростей:
В предыдущем скетче коэффициенты для пропорциональной и дифференциальной составляющих ПД-регулятора были найдены для скорости 60%. Если уменьшить скорость движения машины speed с 60% до 30%, то найденные ранее коэффициенты будут слишком велики, и мы получим перерегулирование.
Выход из положения — найти kP и kD для минимальной и максимальной скоростей машины, после чего вывести формулы зависимости коэффициентов от скорости. Как это сделать для коэффициента пропорциональной составляющей, описано в статье П-регулятор. Но стоит учитывать, что kP имеет более линейную зависимость от скорости speed, чем kD. В нашем примере коэффициент дифференциальной составляющей kD имеет прямую зависимость от квадрата скорости speed, для других систем зависимость будет иной.
Теперь можно написать скетч, у которого скорость можно менять от 20 до 60%:
#include <Wire.h> // Подключаем библиотеку для работы с аппаратной шиной I2C #include <iarduino_I2C_Motor.h> // Подключаем библиотеку для работы с мотором I2C-flash #include <iarduino_I2C_Bumper.h> // Подключаем библиотеку для работы с бампером I2C-flash // iarduino_I2C_Motor mot_R (0x0A); // Объявляем объект mot_R для правого мотора, указав адрес модуля на шине I2C iarduino_I2C_Motor mot_L (0x0B); // Объявляем объект mot_L для правого мотора, указав адрес модуля на шине I2C iarduino_I2C_Bumper bum(0x0C); // Объявляем объект bum для работы с бампером I2C-flash, указав адрес модуля на шине I2C // float i, j; // Переменные для хранения ошибок float speed = 60; // Скорость машины в % float kP = 3 + 0.125*(speed-20); // Коэффициент пропорциональной составляющей float kD = speed*speed/250; // Коэффициент дифференциальной составляющей // void setup(){ // mot_R.begin(); // Инициируем работу с левым мотором I2C-flash mot_L.begin(); // Инициируем работу с правым мотором I2C-flash bum.begin(); // Инициируем работу с бампером I2C-flash mot_R.setDirection(true); // Указываем правому мотору, что его вращение должно быть прямым (по часовой стрелке при положительных скоростях) mot_L.setDirection(false); // Указываем левому мотору, что его вращение должно быть обратным (против часовой стрелки при положительных скоростях) } // // void loop(){ // i = bum.getErrPID(); // Получаем текущую ошибку центрирования линии float P = i * kP; // Вычисляем пропорциональную составляющую float D = (i-j) * kD; // Вычисляем дифференциальную составляющую float PD = P+D; // Получаем значение от ПД-регулятора mot_R.setSpeed(speed - PD, MOT_PWM); // Устанавливаем скорость правого мотора mot_L.setSpeed(speed + PD, MOT_PWM); // Устанавливаем скорость левого мотора }
Этот скетч отличается от предыдущего только тем, что значения kP и kD определены не числами, а формулами.
При изменении значения скорости speed в пределах от 20% до 60%, будут автоматически пересчитываться коэффициенты kP и kD, и машина продолжит корректно двигаться по линии.
Теперь наша машинка может ездить, в том числе, и на высокой скорости.
Недостаток ПД-регулятора:
При движении по прямой линии ПД-регулятор не способен корректировать слабые ошибки. Это выражается в незначительных отклонениях центра бампера от центра прямой линии.
При движении по кругу, дугам и поворотам П-регулятор оставляет незначительную ошибку. Это выражается в смещении центра бампера к внешнему краю линии.
- Влияние П-регулятора тем сильнее, чем больше текущая ошибка;
- Влияние Д-регулятора тем сильнее, чем выше скорость изменения текущей ошибки;
- При движении машины по прямой линии, центр линии находится вблизи центра бампера; текущая ошибка слишком мала и слабо меняется, следовательно, ПД-регулятор не может её скорректировать;
- На поворотах П-регулятору нужна ошибка, иначе он не сможет повернуть, поэтому центр бампера проходит ближе к внешней границе линии;
- Д-регулятор не будет работать, если ошибки считываются слишком быстро, или с разными интервалами;
- Д-регулятор подвержен "шумам", он резко реагирует на некорректные данные;
Обсуждение