Программирование LEGO NXT роботов на языке NXC - Еще раз о моторах

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск

Автор: Daniele Benedettelli

Перевод: © Ботов Антон aka =DeaD=, 2009

Эксклюзивно для www.roboforum.ru
копирование на другие ресурсы и публикация перевода
без разрешения его автора запрещены

Еще раз о моторах

Существует несколько дополнительных команд для моторов, которые вы можете использовать для более точного управления моторами. В этой главе мы обсудим эти команды: ResetTachoCount, Coast (Float), OnFwdReg, OnRevReg, OnFwdSync, OnRevSync, RotateMotor, RotateMotorEx, а также основы ПИД-управления.

Плавная остановка

Когда вы используете команду Off(), сервомотор мгновенно останавливается, блокируя вал и удерживая позицию. Существует способ более мягкой остановки мотора не используя блокировку вала. Для этого используйте команды Float() или что то же самое - Coast(), они просто отключают питание моторов. Вот пример, сначала робот останавливается используя блокировку вала, а потом останавливается без использования блокировки. Обратите внимание на разницу. На самом деле для конкретно этого робота разница достаточно незаметна, но для других роботов эта разница будет гораздо больше.

task main()
{
  OnFwd(OUT_AC, 75);
  Wait(500);
  Off(OUT_AC);
  Wait(1000);
  OnFwd(OUT_AC, 75);
  Wait(500);
  Float(OUT_AC);
}

Дополнительные команды

Команды OnFwd() и OnRev() являются простейшими командами для управления моторами.

Сервомоторы из набора NXT имеют встроенные энкодеры, которые позволяют вам достаточно точно контролировать положение вала и скорость его вращения.

Встроенная в NXT прошивка реализует алгоритм ПИД-управления (Пропорциональный Интегральный Дифференциальный - от названия основных трёх его компонент) положением вала и скоростью его вращения с обратной связью через энкодеры.

Если вы хотите, чтобы ваш робот ездил строго по прямой, вы можете использовать возможность синхронизации двигателей, которая объединяет их в пару, в которой каждый двигатель замедляется, если второй не успевает крутиться с нужной скоростью. Подобным образом вы можете настроить пару моторов на работу в синхронизированном режиме с процентом скорости левого двигателя по отношению к правом, для поворота направо, налево или вращения на месте, при этом траектория будет выполняться достаточно точно. Существует множество команд, которые позволяют полностью использовать возможности сервомоторов из набора NXT!

Команда OnFwdReg(‘ports',‘speed',‘regmode') включает двигатели указанные в ‘ports' на движение вперед со скоростью ‘speed' применяя режим регуляции, который может быть OUT_REGMODE_IDLE, OUT_REGMODE_SPEED или OUT_REGMODE_SYNC. Если выбран режим IDLE, ПИД-регулирование будет отключено; если режим SPEED, Модуль NXT будет регулировать скорость отдельных моторов чтобы получить постоянную скорость, даже если нагрузка на мотор меняется; и наконец, если выбран режим SYNC, пара моторов указанная в ‘ports' работают в синхронизированном режиме, как было описано выше.

Команда OnRevReg() работает так же как и выше, только в другую сторону.

task main()
{
  OnFwdReg(OUT_AC,50,OUT_REGMODE_IDLE);
  Wait(2000);
  Off(OUT_AC);
  PlayTone(4000,50);
  Wait(1000);
  ResetTachoCount(OUT_AC);
  OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED);
  Wait(2000);
  Off(OUT_AC);
  PlayTone(4000,50);
  Wait(1000);
  OnFwdReg(OUT_AC,50,OUT_REGMODE_SYNC);
  Wait(2000);
  Off(OUT_AC);
}

Эта программа показывает различные способы регулирования. Если вы попробуете остановить колёса робота, удерживая их в руках, при первом режиме (IDLE) ничего не будет происходить, во втором режиме (SPEED) попытка замедлить колесо вызовет увеличение мощности подаваемой на этот мотор, так как NXT пытается добиться заданной ему скорости; и наконец, в режиме синхронизации (SYNC), если попытаться остановить одно колесо - второе так же остановится, дожидаясь заблокированного колеса.

OnFwdSync(‘ports',‘speed',‘turnpct') делает то же самое что OnFwdReg() в режиме SYNC, но можно указать 'turnpct' - процент поворота влево\вправо (от -100 до 100).

OnRevSync() делает то же самое что и предыдущая команда, только направления обратные. Следующая программа показывает эти команды в работе: попробуйте менять процент поворота, чтобы увидеть как это влияет на работу двигателей.

task main()
{
  PlayTone(5000,30);
  OnFwdSync(OUT_AC,50,0);
  Wait(1000);
  PlayTone(5000,30);
  OnFwdSync(OUT_AC,50,20);
  Wait(1000);
  PlayTone(5000,30);
  OnFwdSync(OUT_AC,50,-40);
  Wait(1000);
  PlayTone(5000,30);
  OnRevSync(OUT_AC,50,90);
  Wait(1000);
  Off(OUT_AC);
}

И наконец, моторы можно поворачивать на конкретное число градусов (помните, что полный оборот это 360°).

Для обоих следующих команд, вы можете указывать направление вращения моторов или знаком скорости или знаком угла: так что если скорость или знак имеют один и тот же знак - мотор будет крутиться вперед, иначе назад.

RotateMotor(‘ports',‘speed',‘degrees') вращает вал мотора указанного в ‘ports' на ‘degrees' градусов со скоростью ‘speed' (в диапазоне 0-100).

task main()
{
  RotateMotor(OUT_AC, 50,360);
  RotateMotor(OUT_C, 50,-360);
}

RotateMotorEx(‘ports',‘speed',‘degrees',‘turnpct',‘sync', 'stop') это расширение предыдущей команды, которое позволяет синхронизировать два мотора (например, OUT_AC) указывая процент поворота ‘turnpct' (от -100 до 100) и флаг ‘sync' (который может быть или истиной или ложью). Также команда позволяет указать - нужно ли по её завершении блокировать вал двигателя, для этого используется флаг 'stop'.

task main()
{
  RotateMotorEx(OUT_AC, 50, 360, 0, true, true);
  RotateMotorEx(OUT_AC, 50, 360, 40, true, true);
  RotateMotorEx(OUT_AC, 50, 360, -40, true, true);
  RotateMotorEx(OUT_AC, 50, 360, 100, true, true);
}

ПИД-управление

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

Если кратко, он работает так (Я буду говорить об управлении положением вала цифровым контроллером):

Ваша программа задаёт контроллеру требуемое положение R(t); он выдаёт мощность U(t) на двигатель, замеряя положение вала Y(t) встроенными энкодерами и рассчитывает отклонение E(t) = R(t) – Y(t): вот почему это называется контроллер с обратной связью, потому что выходное положение вала мотора возвращается на вход контроллера, чтобы посчитать насколько он сейчас промахивается. Контроллер при этом превращает размер отклонения E(t) в новую команду для двигателя U(t) таким образом:

U(t) = P(t) + I(t) + D(t), где

P(t) = KP·E(t),

I(t) = KI·( I(t–1) + E(t) )

и D(t) = KD·(E(t) – E(t –1)).

Это может выглядеть достаточно сложно для новичка, но я предприму все усилия, чтобы помочь вам объяснить этот механизм. Команда является суммой трёх частей, Пропорциональной части P(t), интегральной I(t) и дифференциальной D(t).

P(t) даёт контроллеру быстроту реакции, но может мешать стабильности в долгосрочной перспективе;

I(t) даёт контроллеру “память”, в том смысле, что накапливает ошибку и компенсирует её, гарантируя долгосрочную стабилизацию в нужном положении;

D(t) даёт контроллеру “возможность предугадывать” (на основе производной из математики), ускоряя время реакции системы.

Я понимаю, что это может всё еще казаться запутанным, на самом деле на эту тему написаны целые научные книги! Но мы всё еще можем попробовать это в реальности с нашим NXT! Простая программа, которая поможет зафиксировать в памяти эту тему:

#define P 50
#define I 50
#define D 50
task main(){
  RotateMotorPID(OUT_A, 100, 180, P, I, D);
  Wait(3000);
}

Функция RotateMotorPID(port,speed, angle, Pgain,Igain,Dgain) позволяет управлять мотором устанавливая различные параметры ПИД-регулятора, отличные от настроек по умолчанию. Попробуйте выставлять следующие значения:

(50,0,0): мотор не поворачивается точно на 180°, так как остаётся нескомпенсированная ошибка

(0,x,x): без пропорциональной части ошибка очень большая

(40,40,0): здесь у нас перелёт, т.е. мотор поворачивается дальше чем надо и потом возвращается

(40,40,90): хорошая точность и время выполнения команд

(40,40,200): вал колеблется, так как дифференциальная часть слишком большая

Попробуйте другие значения, чтобы посмотреть как разные настройки ПИД-регулятора влияют на выполнение команд.

Подводим итоги

В этой главе вы освоили дополнительные команды для управления моторами: Float(),Coast() которые плавно останавливают моторы; OnXxxReg() и OnXxxSync() которые реализуют управление с обратной связью как по скорости, так и по синхронизации со вторым мотором; RotateMotor() и RotateMotorEx() используемые для поворота на нужный угол выходного вала моторов. Вы немного изучили что такое ПИД-регулирование; хотя это было не исчерпывающее объяснение, может быть я вас даже немного запутал, попробуйте поискать материал на эту тему в Интернете!