Официальный сайт компании Arduino по адресу arduino.cc
Езда по линии на ПИД-регуляторе Ардуино
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пнд, 17/12/2018 - 20:03
Есть код робота для езды по линии на основе ПИД-регулятора.
//моторы (драйвер моторов L298N): #define ena 9 // ENA #define in1 8 // IN1 #define in2 7 // IN2 #define in3 13 // IN3 #define in4 12 // IN4 #define enb 11 // ENB // Датчики линии (аналоговые): #define L3 A0 // левый самый крайний датчик #define L2 A1 // левый крайний датчик #define L1 A2 // левый cредний датчик #define R1 A3 // правый cредний датчик #define R2 A4 // правый крайний датчик #define R3 A5 // правый самый крайний датчик int sensorWhite[6]={50,50,50,50,120,50}; // показания датчиков на линии в порядке A0, A1... int sensorBlack[6]={840,875,852,850,877,858}; // показания датчиков вне линии в порядке A0, A1... int k1 = 1; // коэффициент усиления средних датчиков int k2 = 2; // коэффициент усиления крайних датчиков int k3 = 4; // коэффициент усиления самых крайних датчиков // П float up; // пропорциональная составляющая float kp = 0.5; // коэффициент пропорциональной составляющей // И float ui; // интегральная составляющая float ki = 0; // коэффициент интегральной составляющей int iSum = 0; // сам интеграл (сумма) float k_down_i = 0.5; // коэффициент, уменьшающий интегральную составляющую на каждой итерации // Д float ud; // дифференциальная составляющая float kd = 0; // коэффициент дифференциальной составляющей int oldErr; // значение ошибки, полученной на предыдущей итерации unsigned long time = 0; // время получения текущей ошибки unsigned long pastTime = 0; // время получения предыдущей ошибки int maxSpeed = 100; // максимальная скорость int err; int pause = 20; // время задержки void setup() { for (int i = 7; i <= 13; i++) pinMode(i, OUTPUT); } void loop() { err = k1*(map(analogRead(L1), sensorWhite[2], sensorBlack[2], 0, 1000)-map(analogRead(R1), sensorWhite[3], sensorBlack[3], 0, 1000))+ // Приводим показания всех датчиков k2*(map(analogRead(L2), sensorWhite[1], sensorBlack[1], 0, 1000)-map(analogRead(R2), sensorWhite[4], sensorBlack[4], 0, 1000))+ // к одинаковому диапазону, вычитаем k2*(map(analogRead(L3), sensorWhite[0], sensorBlack[0], 0, 1000)-map(analogRead(R3), sensorWhite[5], sensorBlack[5], 0, 1000)); // из показаний правых показания // П левых up = kp * err; // И iSum = iSum * k_down_i + err; ui = ki * iSum; // Д time = millis(); // текущее время ud = kd * (err - oldErr)/(time-pastTime); // de/dt oldErr = err; pastTime = time; float u = up + ui + ud; // управляющее воздействие if (u > 0) {analogWrite(ena, maxSpeed); analogWrite(enb, maxSpeed - u);} else {analogWrite(ena, maxSpeed + u); analogWrite(enb, maxSpeed);} delay(pause); }
Датчики расположены так:
Кому что-то непонятно в коде или еще где, пишите.
Как известно, самое сложное в ПИД-регуляторе - это его настройка, т.е. подбор коэффициентов пропорциональной, интегральной и дифференциальной составляющих. Однако, это еще не проблема, более того, с этим можно довольно просто справиться.
Но ведь поведение робота зависит еще и от таких параметров, как максимальная скорость, время задержки, коэффициент уменьшения интегральной составляющей на каждой итерации и коэффициенты усиления отдельных датчиков, и как найти идеальное соотношение всех этих параметров - большой ворпрос.
Если кто-то поможет, буду благодарен.
http://arduino.ru/forum/obshchii/skorostnoe-dvizhenie-po-linii-kak
ПС: По мне вы потеряли еще один ряд датчиков.
Как известно, самое сложное в ПИД-регуляторе - это его настройка, т.е. подбор коэффициентов пропорциональной, интегральной и дифференциальной составляющих. Однако, это еще не проблема, более того, с этим можно довольно просто справиться.
Но ведь поведение робота зависит еще и от таких параметров, как максимальная скорость, время задержки, ... и коэффициенты усиления отдельных датчиков, и как найти идеальное соотношение всех этих параметров - большой ворпрос.
Ну, собственно, коэффициенты ПИДа и будут зависить от этих параметров. Если с " этим можно довольно просто справиться", то какие проблемы?
коэффициент уменьшения интегральной составляющей на каждой итерации
А это и есть коэффициет "П".
Для начала, переделайте код. Например, посмотрите,что будет 65 строке если u > MaxSpeed?
И еще, максимальная возможная скорость зависит, в том числе, от того, от частоты с которой ПИД может подавать управляющее воздействие. Float арифметика на ардуино очень медленная. Рекомендую переделать на целочисленную. При этом следут учесть, что максимальное осмысленное значение которое можно передавать в analogWrite это 255.
http://arduino.ru/forum/obshchii/skorostnoe-dvizhenie-po-linii-kak
ПС: По мне вы потеряли еще один ряд датчиков.
http://arduino.ru/forum/obshchii/skorostnoe-dvizhenie-po-linii-kak читаю перед сном.
Как показывает практика, и на одной линии датчиков может ехать очень быстро. Недавно ездил на соревнования, там победил вот такой драндулет:
Ну, собственно, коэффициенты ПИДа и будут зависить от этих параметров.
Не согласен
А это и есть коэффициет "П".
??? Похоже, Вы не совсем поняли.
Здесь ui - коэфф И-составляющей, а k_down_i - коэфф, на который интеграл умножается каждый раз, чтобы не зашкаливать.
Например, посмотрите,что будет 65 строке если u > MaxSpeed?
С этим должны справиться коэффизиенты. Но можно и map еще один сделать...
И еще, максимальная возможная скорость зависит, в том числе, от того, от частоты с которой ПИД может подавать управляющее воздействие.
Вот именно, за это и отвечает переменная pause, и чему она должна равняться - часть моего вопроса. Как я понял, частота не должна быть максимальной. Речь идет о какой-то оптиматьной частоте. Вот, что об этом написано на http://robofob.ru/materials/articles/pages/Karpov_mobline1.pdf:
"Дело в том, что если частота управления слишком маленькая, то мы не получим эффективную систему. Более того, при малой частоте управления мы можем получить систему, которую вообще невозможно стабилизировать. Но и при слишком большой частоте мы тоже получим плохой результат: начнут возникать серьезные шумы в дифференциальной компоненте, а также начнет переполняться интегратор".
Float арифметика на ардуино очень медленная. Рекомендую переделать на целочисленную. При этом следут учесть, что максимальное осмысленное значение которое можно передавать в analogWrite это 255.
Спасибо, учту
Там много "факторов". Начать надо с того, что простой (типовой) ПИД регулятор - не подходит для движения по линии, поскольку она, линия имеет несколько разных форм своего изгиба. Если уж и ПИД, то надо иметь их "пакет" на каждую кривую. Если речь о трассе Робофест, где уже нормально достигнуты скорости прохождения в 6.0 секунд, то она ваще рисована "от руки" в смысле там нет "типовых кривых".. что практически снижает интерес к ПИД до нуля.
Далее (поскольку свое мы уже откатали - вышли из этого возраста): есть 2 "главных" режима движения: "ситуация ухудшается" и "возврат на линию". Это разные настройки ПИД, как показывает мат. моделирование движения. Там нужен сильный "гистерезис" параметров, что ещё больше усложняет настройку.
И да, в вещественных числах ПИД - не справится по скорости управления. Для достижения времен в 6сек и меньше, требуется "максимальная скорость по прямой" - не ниже 5 метров в сек. Поскольку скорость в повороте в среднем в 2 и более раз ниже. Хорошо, если средняя скорость по трассе будет хотя бы вполовину от макс. возможного предела. Чаще - треть. 5м/сек - это 5мм в миллисекунду, "инерция тележки" дает периодичность управления в районе 16мсек .. 10-12 для "предельно облегченной" весом в 100-120 грамм. (из моей мат. модели).
И последнее: КАК Вы это будете (гистерезис, разные ПИД их настройка через методики "собственной частоты рысканья") разьяснять детишкам - у судей должно возникать "множество вопросов" (пока они закрывали на это глаза).
Есть подход проще и доступнее детям: управление тележкой через набор массивов управляющих коэффициентов (почти ПИД, но гибче). Ошибку линии превращаете в целое число, которое является индексом для массива настроечных к-тов. Здесь же можете менять группы массивов в зависимости от ситуации: теряете линию или возвращаетесь к ней - тот самый гистерезис управления. А также вносить доп. коррективы в "Д" в зависимости от отношения текущей скорости к максимальной на моторах, а также в зависимости от "крутизны" линии.
Этот подход - вполне легко разьяснить ребенку с его уровнем математики и без ПИД.
Наш (правда домашний) рекорд - 5.6сек на тележке весом в 125гр с "прилипающими" (силиконовыми) колесами с к-том трения около 1.4 (да, да .. больше единицы :) ). Система мотор-редуктор-колесо - самая важная часть. К сожалению, покупных вариантов, позволяющих "выжать" предельные параметры согласно мат модели - в продаже нет. Неплохие колеса можно отлить самому из .. обыкновенного казанского силикона для авто (белый). Но хранить их можно только в "подвешенном" состоянии (у нас уже они "квадратные"). Редуктор не стоит брать с большим понижением - растет момент инерции колеса на моторе, что сильно смягчает управляющую характеристику тележки в целом. 10:1 - наверно оптимально. Моторы .. тут "*опа - полная". Подходящих моторов нет, лучшее это мотор-редуктор Мабуччи (11:1) по 2500руб/шт, но и их придется сильно форсировать, поэтому на соревнование надо ехать с запасом в 1-3шт. и уметь "менять на ходу" за короткое время (без пайки).
Самодельные моторы, просто на ура получаются пересборкой якорей обыкновенных 130 моторов (полно в детских игрушках, на Али можно найти и по 25руб/шт в партии от 10шт): надо на якорь набирать не менее 16 пластин. Влезает до 20. Лучшее кол-во 18. Перемотка якоря проводом ПЭВ-2 0.125 по 210 витков на обмотку (100% заполнение каркаса якоря). Виток к витку, аккуратно и одновременно все 3 обмотки (симметрично для сохранения центровки якоря). Мотаем послойно каждую обмотку, с первыми 50-ю витками на каждую (там они ещё не мешают друг другу). Строго виток к витку. Каждый слой аккуратно (зубочисткой дабы избежать соскабливания изоляции и одинаково капнуть кол-во клея) проклеиваем цианакрилатом. Лучше мотать под лупой.
Далее, к этому якорю ищем корпус с усиленной магнитной системой. Подходят от той же Мабуччи, Downsoll и др. Они у них так и зовутся на Али "strong magnetic system". Перемотанный мотор в итого весит около 24-25гр, имеет сопротивление якоря около 7 ом (около 10 ом на обмотку) и на мосфетном(!) драйвере под 2S Li-ion (7.2-8.4в) имеет тягу (на токе 1А) останавливающего момента под 100гр*см. и обороты не хуже 12-16тыс в мин на холостом ходу. Холостой ток не должен превышать 40-70мА - это признак качества переделки - малое трение в моторе и хорошая центровка якоря.
Легкий мосфетный драйвер тоже придется паять самому. Тут есть тема про него, где есть несколько схемных решений. Нормально на базе АО4606 его можно упихать в размер 16х32мм и иметь приемлемую токоотдачу в 5 ампер и напругой до 30вольт. Работает на ура - проверено неоднократно.
Для снижения общего веса - подбирайте аккумулятор строго по времени прохождения трассы. для 125гр тележки пара 680мач - более чем достаточно. Лучше заменить аккум. перед карантином (прокатив 1 раз!) чем иметь тяжелую тележку. Соответственно, иметь с собой достаточное кол-во зарядников или один на несколько аккумов или "ведро" аккумуляторов.
Мелкие пакости: на карантин нельзя ставить тележку с "настроенным" аккумулятором: он подразряжается в процессе настроек, нагревается и т.д. А на карнтине он .. остывает и выдает несколько иное напряжение и просадку .. в итоге тележка едет "не туда" или не так. Надо заменять аккум, прогнать его ровно 1 раз (потренировать чутка и очень) убедится что все ладно и ставить на карантин.
Датчики. Ну я оних много писал в разных темах. Ключевое явление - усреднение от 3 до 5 замеров с исключением боковой засветки. Наши ездят даже в полной темноте и на солнечном свету (засветка трассы) - одинаково. Тоже - лучше самодельный вариант (за 3 копейки) чем покупные, особенно от Polulu. Да, с учетом скоростей на трассе - типовой замер от "Ардуино" - не справится по скорости замера. Имейте это ввиду.
Вообще, если хотите пользовать "типовые библиотеки" - лучше сразу переходить на 32-битные МК с тактовой частотой не ниже 160Мгц и встроенным float (Успешно применяют Teensy 3.0 и старше). Чтобы заставить Нану шустро бегать по линии - придется попотеть. :)
Для целочисленной ошибки линии, датчики должны иметь строго определенную базу промеж себя, а именно - 2/3 от ширины линии при нечетном количестве - один по центру.
В итого, общая стоимость скоростной тележки по линии с претензией на рекорд не обходится дешевле 10-15тыс. руб. :)
.. вроде все. Местные идиоты могут не возбуждаться, отвечать не буду.
Как-то вы не лестно о форумчанах ... ;) А не подскажете где с вами пообщаться можно на сходные темы?
arhat109@mail.ru пишите. Это "публичная почта" для всех желающих.
И последнее: КАК Вы это будете (гистерезис, разные ПИД их настройка через методики "собственной частоты рысканья") разьяснять детишкам - у судей должно возникать "множество вопросов" (пока они закрывали на это глаза).
Мне самому как бы 15 лет...
Там много "факторов". Начать надо с того, что простой (типовой) ПИД регулятор - не подходит для движения по линии, поскольку она, линия имеет несколько разных форм своего изгиба. Если уж и ПИД, то надо иметь их "пакет" на каждую кривую. Если речь о трассе Робофест, где уже нормально достигнуты скорости прохождения в 6.0 секунд, то она ваще рисована "от руки" в смысле там нет "типовых кривых".. что практически снижает интерес к ПИД до нуля.
Не понял, почему типовой ПИД не потянет "трассу, рисованную от руки". Понятно, что максимальную скорость прохождения он не даст, но все равно, движение будет довольно ровным и быстрым.
Если у Вас 1 ПИД (один комплект настроечных параметров), то он будет "оптимален" только для некоторой "средней" кривизны трассы. во всех остальных местах трассы он даст потерю скорости перемещения и чем "плавнее" будете настраивать для всей трассы - тем больше будет потеря. Ну и по большому счету там ПИД не нужен вовсе:
Движение в повороте - можно делать и вовсе без ПИД, опираясь только на радиус поворота, смещение центра тяжести и центробежную силу (зависит от геометрии тележки и сильно), выноса и величины трения передней опоры и .. механической характеристики мотора. Ничего больше для предельного движения по радиусу - не требуется. Упрощая, можно сказать что там обыкновенная кубическая зависимость ШИМ на моторах от радиуса поворота. Собственно это весь ваш "П" в ПИД.
Далее, величина ошибки при целочисленном управлении меняется не плавно, а "скачками", и вынос датчиков от оси вращения тележки (центр оси ведущих колес) - существенно влияет и фактически "формирует" некоторые фиксированные радиусы, на которых тележка едет "оптимально" при фиксированном управлении. Соответственно, подбор выноса датчиков к трассе - может значительно упростить как настройку так и само управление.
И как уже написал выше: есть существенная разница в управляющих параметрах в зависимости от ситуации: тележка теряет трассу или наоборот возвращается на неё. При одних и тех же скоростях на моторах - управление сильно разное (гистерезис). Так, если тележка теряет трассу, то величина изменения ШИМ моторов может быть .. меньше, чем при обратном движении - тележку надо "успокоить" при возврате на трассу быстрей, чем при её потере. "Д" - должен быть разным и его диапазона может просто оказаться недостаточным.
Ну и вообще, "Д" - тут не совсем то, что под ним понимается: при целочисленном изменении ошибки ваше "Д" фиксируется +-1 .. надо ещё считать "как давно" вы едете на этой величине ошибке: возможно движение на боковом датчике в повороте - когда тележка не выравнивается в ноль ошибки, а едет с фикс. ошибкой, но .. ровно.
Движение на боковом датчике дает преимущество на спрямленном участке после поворота - проще выход ибо датчик был боковой и ошибка просто перемещается к середине обратно, а не "скачет" туда-сюда через ноль.
Я бы начал с того что в 49 строке
поменял к2 на к3.
В общем, выпилился из темы, кому надо - пишите на почту.
Есть более изящьный алгоритм. Помимо датчиков на одно колесо вешается энкодер. И когда энкодер срабатывает новое число заносится в буфер, а старое выбрасывается. А теперь вычисляется арифметическая сумма правой стороны линии и с левой. Вот если суммы совпадают, то мы идем строго по линии, а если в одной стороне стало меньше , то ее надо притормаживать. Вот это и есть ваше интегрирование на практике.
Не вполне понял, что Вы имеете в виду.
Что понимается под "арифметической суммой правой стороны линии и с левой", при чем тут энкодер, что нам дает равенство площадей, как это связано с интегральной составляющей и в чем вообще суть?
Александр, не переживайте. Мы тут все квона не с первого раза понимаем. А иногда и не со второго. Но, порой, он одумывается и объясняет, что имел ввиду.
Попробую в картинках. А то не все математику знают к сожелению. Разместим датчики
так
сожаление - проверочное жало-сть, а то про какое-то желе получилось
Вы так ине ответили на мой вопрос о том, что к чему
А вот если будет энкодер, то замеры можно делать регулярно и тогда можно вычислить площади А и В
Я когда делал паяльник, делал в 2 вариантах прошивку. С PID и без, точнее P регулятор.
Так вот P мне понравился гораздо больше, гораздо быстрее выходит на рабочий режим, не нужно накопления интегральной составляющей и т.д. Но не без недостатков, который с одной стороны не недостаток, а вот компенсировать я его не смог коэффициентами напрямую. Но влиял на сам коэффициент P так сказать, а сейчас мысль пришла что нужно было коэффициент к шиму добавлять, а не к P. А недостаток на примере паяльника что стабилизировалась на температуре, которая "подходила" системе. Вместо 250градусов было в районе 180. Но очень точно и быстро на нее выходила по сравнению с PID
То есть стремиться что бы площадь А равнялась В
А зачем нам эти площади и счто нам даст их равенство, вот, что непонятно
Ну как нипонятно. Поставим машину строго перпендикулярно линии, так чтоб условие "площадь А равнялась В" соблюдалось. Такое положение не допускает движение при сохранении сцепления колес и без нарушения заданого условия. Но ведь телега и не должна ехать перпендикуярно линии! Таким образом выполнение условия "площадь А равнялась В" исключает перемещение телеги перпендикулярно линии и соответственно сход с неё. Все строго! Существует и трехмерное аналогичное правило - для движения по заданой траектории, плоскость этой траектории должна разделять объем модели на равные части. Больше строгости в утверждениях ;)
Римейк картины художника Петрова-Водкина: Купание сферического коня в вакууме.
Logik, по-моему Вы шутите. С чайником (каков я) шутки плохи. Сгореть может - и ничего не останется.
Я когда делал паяльник, делал в 2 вариантах прошивку. С PID и без, точнее P регулятор.
Так вот P мне понравился гораздо больше, гораздо быстрее выходит на рабочий режим, не нужно накопления интегральной составляющей и т.д. Но не без недостатков, который с одной стороны не недостаток, а вот компенсировать я его не смог коэффициентами напрямую. Но влиял на сам коэффициент P так сказать, а сейчас мысль пришла что нужно было коэффициент к шиму добавлять, а не к P. А недостаток на примере паяльника что стабилизировалась на температуре, которая "подходила" системе. Вместо 250градусов было в районе 180. Но очень точно и быстро на нее выходила по сравнению с PID
Logik, по-моему Вы шутите. С чайником (каков я) шутки плохи. Сгореть может - и ничего не останется.
у меня тоже чайник сгорел, когда прохождение на УКВ было, а чайник поставил на плиту, пришлось срочно ехать на базу и брать и нержавейки )))
Римейк картины художника Петрова-Водкина: Купание сферического коня в вакууме.
После 150 армянского коньяка сложно представить сферического коня в вакууме )))
Logik, по-моему Вы шутите. С чайником (каков я) шутки плохи. Сгореть может - и ничего не останется.
Ну вот, не все так и плохо. Не сгорит - закалится.
Logik, по-моему Вы шутите. С чайником (каков я) шутки плохи. Сгореть может - и ничего не останется.
Он с квоном шутит. Вы тут совершенно непричем. Гонками тут только Архат занимался (во всяком случае - на словах), так что не принимайте на веру и свой счет все написанное.
Logik, по-моему Вы шутите. С чайником (каков я) шутки плохи. Сгореть может - и ничего не останется.
Ну какой там тролинг, просто попытка доказать Великую теорему qwone о равенстве площадей.
Это называется "недостаток"? Не кажется, что слова "устройсво непригодно" точнее?
...из поганых болот чьи-то тени встают...
Ну какой там тролинг, просто попытка доказать Великую теорему qwone о равенстве площадей.
Опаньки. То истину рекли, картинками нас радовали, а теперь чё уже "хорошая цепь, но не моя"!
есть преположение, что Пух провел диагональ в своем квадрате обратного времени
https://yadi.sk/i/xnjhZvOUb424Gw
С такой огромной скоростью ездит наша огромная машина.
Особенно впечатляет скорость на поворотах
Расстояние между датчиками должно быть чуть меньше чем ширина линии если их 6 или больше если их два.
А все-таки, что Вы имели в виду про площади? Что они дают?
А все-таки, что Вы имели в виду про площади? Что они дают?
А это Вам как?
А как Вы поступите в этих вариантах
Будете ехать прямо или там где меньше площадь будете замедлять?
вопрос на засыпку: что такое производная от кривой? В некотором смысле это наклон касательной в данной точки (относительно оси движения) т.е. литера Д в аббревиатуре ПИД. Как мне видится, qwone, подразумевает под площадью литеру И от ПИД (центровка авто на линии). Но не то, ни другое не даст 1) представление о будущем изменении характера кривой, что для ПИД важно. 2) значительно нагрузит математикой контроллер. Arhat109-2 прав (ИМХО) массивЫ с уже готовыми значениями, а не непосредственные вычисления ПИД предпочтительнее т.к. получение данных (разрешающая способность датчиков) очень низкая. В данном случае основой является вычисление времени между событиями приведенное к скорости движения. (событие - изменение состояния любого датчика). К сожалению, не имею опыта в решении подобных задач, и точно также попытался бы прилепить ПИД, а потом бы все одно перешел бы к готовым массивам и высвободил бы ресурс процессора в сторону точного определения времени - ИМХО. Ну и попутно бы решал проблему с возвратом на линию в случае ее потери - т.к. задачи связаны и следуют одна из другой.
А ещё для чистоты эксперимента можно добавить аппаратных решений - возможность смещения датчиков в двух координатных осях.
leks, что за картинка? вынос датчиков с удалением от корпуса тележки?
А ещё для чистоты эксперимента можно добавить аппаратных решений - возможность смещения датчиков в двух координатных осях.
сканирование?
Нет там никакой сложной математики. Шифтом снять показания всех датчиков и определить сколько датчиков с правой стороны и сколько с левой от линии. Площадь она не сильно меняется. Добавить приращение к площади и убрать старое которое было 5-10 измерений назад. Массива байт хватит с головой для сохранения новых значений. А дальше сравнение значений переменных А и В . Коррекция шимов.
Просто я далёк от ПИД, но мне кажется, что положение-удаление линейки датчиков от центра масс тележки очень важная составляющая в удержании линии на большой скорости. Сам я решал задачу просто удержания линии... на вибромоторах с двумя датчиками и без колёс :)