В этом уроке
- П-регулятор и за что он отвечает
- Настройка регулятора
- Управление машинкой с помощью П-регулятора
Видео версия урока
Общие сведения о П-регуляторе:
П-регулятор (пропорциональный регулятор) — самый простой из возможных способов регулирования. На самом деле, мы уже использовали его в уроке "Движение по линии", просто не называли его так.
- Мы узнавали функцией getLineDigital(), под каким датчиком бампера находится линия.
- Если линия находилась под центральным датчиком, то левый и правый мотор вращались с одинаковой скоростью, следовательно, машина ехала прямо.
- Если линия уходила от центрального датчика влево или вправо, то скорость левого и правого мотора начинала отличаться, следовательно, машина поворачивала, следуя за линией.
- Чем дальше линия уходила от центра бампера, тем сильнее отличалась скорость левого и правого мотора, следовательно, более резким был поворот.
Именно так и работает П-регулятор. Разница скоростей моторов (выходная величина) меняется пропорционально степени отклонения линии от центра бампера (входная величина).
Пропорциональный регулятор изменяет выходную величину пропорционально текущему значению входной величины.
Код созданного нами ранее П-регулятора можно сильно сократить, если вместо нескольких функций getLineDigital(), которыми мы проверяли наличие линии под датчиками, использовать одну функцию getErrPID(), возвращающую ошибку в виде числа от 0 до ±4,5.
- 0 — нет ошибки, центр линии находится под центральным датчиком бампера;
- ±0,5 — центр линии находится между центральным и соседним с ним датчиком;
- ±1.0 — центр линии находится под датчиком, соседним с центральным;
- ±3.5 — центр линии находится между самым крайним и соседним с ним датчиком;
- ±4.0 — центр линии находится под самым крайним датчиком;
- ±4.5 — центр линии потерян, знак указывает на сторону потери линии;
- Если ошибка с отрицательным знаком, то это значит, что линия находится левее центра бампера.
Дополнительное задание.
Выведите в монитор порта значение ошибки ПИД-регулятора. Перемешайте бампер над линией и посмотрите, как меняются значения.
#include <iarduino_I2C_Bumper.h> // Подключаем библиотеку для работы с бампером I2C-flash iarduino_I2C_Bumper bum(0x0C); // Объявляем объект bum для работы с бампером I2C-flash, указав адрес модуля на шине I2C // void setup(){ // Serial.begin(9600); // bum.begin(); // Инициируем работу с бампером I2C-flash } // void loop(){ // Serial.println( bum.getErrPID() ); // Выводим ошибку центрирования линии в монитор delay(500); // } //
Перед созданием кода с П-регулятором давайте определимся с задачами:
Как должен работать код движения по линии:
- Если ошибка равна 0, значит, машина должна ехать прямо, двигаясь по линии;
- Если ошибка меньше 0, значит, машина должна повернуть влево, следуя за линией;
- Если ошибка больше 0, значит, машина должна повернуть вправо, следуя за линией;
- Чем сильнее ошибка отличается от 0, тем сильнее линия отклонилась от центра бампера;
- Для поворота влево нужно уменьшить скорость левого колеса и увеличить скорость правого;
- Для поворота вправо нужно уменьшить скорость правого колеса и увеличить скорость левого;
- Чем выше разница скоростей колёс, тем круче поворот машины.
Настройка П-регулятора:
- Задача П-регулятора — получить значение ошибки и выдать то число, на которое должны отличаться скорости колёс;
- Если П-регулятор просто вернёт значение ошибки, этого может быть либо недостаточно для манёвра, либо слишком много;
- Поэтому П-регулятор умножает значение ошибки на некий коэффициент kP;
Код П-регулятора умещается в одну строку: P = bum.getErrPID() * kP; - Настройка П-регулятора заключается в поиске оптимального коэффициента kP:
- Слишком высокий коэффициент приведёт к тому, что машина будет сильно "вилять" даже на прямой линии. Это называется перерегулированием;
- Слишком низкий коэффициент приведёт к тому, что машина на поворотах будет далеко выезжать за пределы линии трассы. Это называется недорегулированием;
- Оптимальным является коэффициент, при котором бампер машины не покидает линию на всех поворотах трассы, при этом машина не "виляет" на прямых участках.
- Коэффициент П-регулятора является константой, только если машина движется с одной скоростью.
Коэффициент регулятора определяет силу воздействия регулятора.
Чем больше коэффициент, тем сильнее меняется выходная величина.
Скетч для одной скорости:
Скорость колёс в скетче задаётся функцией setSpeed() в процентах.
Выберем скорость машины, равную 60%. Предположим, что на данной скорости машина проходит все повороты и не виляет при 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 speed = 60; // Скорость машины в % float kP = 8; // Коэффициент П-регулятора // 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(){ // float P = bum.getErrPID() * kP; // Получаем значение от П-регулятора mot_R.setSpeed(speed - P, MOT_PWM); // Устанавливаем скорость правого мотора mot_L.setSpeed(speed + P, MOT_PWM); // Устанавливаем скорость левого мотора }
Дополнительное задание.
Попробуйте изменить коэффициент П-регулятора kP и посмотрите на результат.
Проверим работу скетча:
- Если линия находится под центром бампера, то функция bum.getErrPID() вернёт 0, значит, результат П-регулирования P также будет равен 0;
- Скорость правого колеса = 60% - 0 = 60%;
- Скорость левого колеса = 60% + 0 = 60%;
- Машина едет прямо.
- Если линия сместилась влево на полдатчика, то функция bum.getErrPID() вернёт -0,5, значит, результат П-регулирования P будет равен -0,5 * 8 = -4;
- Скорость правого колеса = 60% - -4 = 64%;
- Скорость левого колеса = 60% + -4 = 56%;
- Машина плавно поворачивает влево.
- Если линия под бампером сильно сместилась вправо, то функция bum.getErrPID() вернёт 4, значит, результат П-регулирования P будет равен 4 * 8 = 32;
- Скорость правого колеса = 60% - 32 = 28%;
- Скорость левого колеса = 60% + 32 = 92%;
- Машина круто поворачивает вправо.
Скетч работает корректно.
Скетч для диапазона скоростей:
В предыдущем скетче коэффициент П-регулятора был найден для скорости 60%. Если уменьшить скорость движения машины speed с 60% до 30%, то найденный ранее коэффициент П-регулятора kP будет слишком велик. Машина на такой скорости будет сильно вилять даже на прямой линии, и мы получим перерегулирование.
Выход из положения — найти kP для минимальной и максимальной скоростей машины.
Для начала немного математики:
- Допустим, мы хотим регулировать скорость движения машины в пределах от 20% до 60%;
- kP для скорости 60% мы уже подобрали равным 8;
- Предположим, что kP на скорости 20% равно 3;
- Значит, у нас есть 2 пары значений (скорость 20, коэффициент 3 и скорость 60, коэффициент 8);
- Сначала разделим разницу коэффициентов на разницу скоростей: (8-3) / (60-20) = 0,125;
- Теперь получим формулу зависимости коэффициента kP от скорости speed:
- kP = 3 + 0,125*(speed-20). // тут мы подставили коэффициент 3 и его скорость 20;
- kP = 8 + 0,125*(speed-60). // тут мы подставили коэффициент 8 и его скорость 60.
- И первая, и вторая формула будут давать одинаковые результаты.
Теперь можно написать скетч, у которого скорость можно менять от 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 speed = 60; // Скорость машины в % float kP = 3 + 0.125*(speed-20); // Коэффициент П-регулятора // 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(){ // float P = bum.getErrPID() * kP; // Получаем значение от П-регулятора mot_R.setSpeed(speed - P, MOT_PWM); // Устанавливаем скорость правого мотора mot_L.setSpeed(speed + P, MOT_PWM); // Устанавливаем скорость левого мотора }
Этот скетч отличается от предыдущего только тем, что значение kP определено не числом, а формулой.
При изменении значения скорости speed в пределах от 20% до 60% будет автоматически пересчитываться коэффициент kP, и машина продолжит корректно двигаться по линии.
Важно: скорость моторов можно изменить, используя не только переменную speed, но и напряжение, подаваемое на моторы с помощью подстроечного резистора (10 пункт в уроке о сборке машинки). Только не включайте машинку на длительное время при повышенном напряжении, — помните, что моторы не рассчитаны на него.
Недостаток П-регулятора:
Недостатком П-регулятора является то, что он не может работать на больших скоростях.
Чем выше скорость, тем сильнее приходится поднимать коэффициент kP для преодоления крутых поворотов трассы. А чем сильнее поднимается коэффициент kP, тем больше машина начинает "вилять" на прямых участках трассы.
Это небольшой, но очень важный урок. Пожалуйста, убедитесь, что Вы поняли его смысл и у вас нет вопросов. Только после этого рекомендуем двигаться дальше.
Обсуждение