Две сервы
- Войдите на сайт для отправки комментариев
Вс, 10/03/2013 - 21:44
Если скажу что новичек,то это мягко сказанно.Из опыта лишь робот по линии.
Три дня пытался написать что путное для управления двумя сервами,но воз и ныне там.
Как управлять двумя сервами не зависимо друг от друга,то есть цель такова-одна серва клонит тело шагающего робота влево,удерживая в таком положении вторая серва отклоняет его ногу вперед,первая сера клонит тело вправо и удерживая тело вторая серва движется назад.
Первоначально обои сервы установлены в нейтраль тобишь 90 градусов.
Меньше 90 градусов наклон влево,больше 90 наклон вправо
Аналогично и с передвижениями вперед-назад
#include <Servo.h> Servo myservo1; Servo myservo2; void setup() { myservo1.attach(9); // наклоны влево впрво myservo2.attach(11); // движения вперед назад } void loop() { myservo2.write(95); // движение правой ноги delay(50); myservo2.write(100); delay(50); myservo2.write(105); delay(50); myservo2.write(110); delay(50); myservo2.write(115); delay(50); myservo2.write(120); delay(50); myservo2.write(115); delay(50); myservo2.write(110); delay(50); myservo2.write(100); delay(50); myservo2.write(95); delay(50); myservo2.write(90); delay(2000); myservo2.write(85); // движение левой ноги delay(50); myservo2.write(80); delay(50); myservo2.write(75); delay(50); myservo2.write(70); delay(50); myservo2.write(65); delay(50); myservo2.write(60); delay(50); myservo2.write(65); delay(50); myservo2.write(70); delay(50); myservo2.write(75); delay(50); myservo2.write(80); delay(50); myservo2.write(85); delay(50); myservo2.write(90); delay(50); myservo1.write(95); // наклон влево delay(50); myservo1.write(100); delay(50); myservo1.write(105); delay(50); myservo1.write(110); delay(50); myservo1.write(115); delay(50); myservo1.write(120); delay(50); myservo1.write(125); delay(50); myservo1.write(130); delay(50); myservo1.write(135); delay(1200); myservo1.write(90); // наклон вправо delay(50); myservo1.write(85); delay(50); myservo1.write(80); delay(50); myservo1.write(75); delay(50); myservo1.write(70); delay(50); myservo1.write(65); delay(50); myservo1.write(60); delay(50); myservo1.write(55); delay(50); myservo1.write(50); delay(1200); }
Спасибо, на счет медленого движения стало попроще.Но не совсем выполняется условие перемещения.Обои серы ведь начинают двигаться одновременно,а необходимо вначале наклон и после этого движение вперед.Пытался с паузами,и менял 17 и 18 строку ставил над 16,чтобы наклон начинался раньше движения.
Попробуй условия выставить что пока один тип движения не отработает другой тип движения не запуститься.
Знал бы прикуп,то сделал бы обязательно.Первоначально вся механика тестилась на радиоуправлении,проблем не было,можно было выставить любые и миксы и расходы.Левым стиком передатчика управлялись наклоны,правым передвижения.Теперь чешу репу.
Проблема в том, что предполагаете наличие телепатов. Прочитайте свое стартовое сообщение и попробуйте найти в нем описание чем же вас не устраивает написанный вами скетч. В чем проблема состоит-то? Догадайтесь? Вот Максим и попытался догадатся, предположил что проблема именно не в одновременности движении серв. И решил именно эту проблему. А оказывается вам как раз и не нужно одновременно, значит он зря потратил время :(
Если же вам нужно "по очереди", то ваш изначальный скетч - как раз то что нужно. Просто вы не дали первой серве достаточно времени для поворота. Просто увеличте вермя delay-ев, что-бы она гарантированно успевала встать в нужную позицию до того как пойдут команды для второй сервы (да и свою черду команд успевала отработать).
Как управлять двумя сервами не зависимо друг от друга,то есть цель такова-одна серва клонит тело шагающего робота влево,удерживая в таком положении вторая серва отклоняет его ногу вперед,первая сера клонит тело вправо и удерживая тело вторая серва движется назад.
Проблема как раз в том, что не удавалось расставить грамотно паузы.
Максиму ОГРОМНОЕ спасибо понял что можно упростить плавное движение серв,а на счет ЕГО зря потраченного времени-пусть напишет об этом сам.
>удерживая в таком положении
Для этого не нужно ничего специально делать. Суть сервы в том и состоит что-бы удерживать последний заданный угол. Пока у нее хватает физических сил и на нее идет управляющий PWM (то есть пока вы не сдеалете detach)
>Проблема как раз в том, что не удавалось расставить грамотно паузы.
Ну вот это и нужно было в старт написать. А время задержки их нужно либо методом "научного тыка" (и никто вам их не скажет, так как это зависит именно от скорости ваших серв), либо "вычислять". Делаете тестовый скетч. В нем поворачиваете серву на 180-градусов. И засекаете сколько времени это занимает. Опят-таки, либо "на глаз", либо можно два проводочка прикрепить, что-бы в положении 180 она их замыкала и в сериал выводить когда это произошло (ну либо секундомер в руки).
Делите намерянное время на 180 и получаете сколько занимает поворот на один градус. Далее когда вам нужно повернуть серву берете ее текущие положение отнимаете его от требуемого нового и разницу умножаете на время поворота на один градус. На полученное время и делаете delay(). Тогда она будет и "успевать" и "не будет лишнего дуплить". Можно еще к этому высчитанному времени, накинуть 10-20 миллисекунд для верности (погрешности измерений и вычислений). Подбираем эту цифру "что-бы на глаз рывков видно небыло".
>-пусть напишет об этом сам
Не нужно топорщить перья. Даже если Максим ничего не имеет против подобного время-провождения - это не отменяет способности других дать оценку. Воспринимайте это как совет/сторонее мнение "как это выглядело со стороны". Конечно вы имеете полное право наплевать на это мнение, но неповторение подобных ошибок (осутсвие четкого описание проблемы) - поможет ВАМ в будущем быстрее находить решение проблем с помощью форума.
Принцип работы сервы прекрасно знаю,не понятно можно ли перед командой myservo.write ставить delay
>Не нужно топорщить перья
Даже и в мыслях не было,я гладкошерстный
Максим, ОГРОМНОЕ СПАСИБО,попытаюсь уразуметь весь код до конца.Но если тяму не хватит то необессутьте за глупые вопросы.
Принцип работы сервы прекрасно знаю,не понятно можно ли перед командой myservo.write ставить delay
Ну а почему нет? (тем более что так или иначе вы все равно это делаете). delay - это просто остановить скетч и ничего не делать. При этом на выходы продолжают поступать те pwm-мы которые который вы дали последней командой myserwo.write. delay() перед новой write означает только одно - серве не поступет НОВАЯ команда пока не пройдет время delay(). И в это время она будет держать "старую позицию".
А вообще - использовать delay() (а также pulseIn и т.п.) в более-менее сложных скетчах - практически не возможно. В данном случае у вас он подходит (и оправдан своей простотой), так как вам нужно по очереди... но предположим что вы захотите еще реагировать на какие-то сонары, или нажатие кнопок пока идет движение сервы... и delay будет вам портить всю малину. Так как в момент его исполнение датчики не опрашиваются, реакции на кнопки - нет (если не использовать прерывания, а их мало).
И тут вам нужно будет пойти посмотреть на пример "мигаем диодом без delay()", а также кучу подобных веток как работать со временем без delay()
Да и в более менее правдоподобном роботе - вероятность одновременного и согласованного движения серв рано или поздно потребуется (так что в этом смысле Максим не зря тратил время). Можете еще попробовать поиском поискать. Была пара месяцев назад тема где решалась проблема именно синхронного и плавного вращения двух серв одновременно.
>Не нужно топорщить перья
Даже и в мыслях не было,я гладкошерстный
Ну и у меня, сегодня, гавкатся настроения нет ;) Тем более что до "нормальной темы" вы не дотянули совсем чуть-чуть ;) Некоторые и тему назовут уникально "помогите новичку" и скетч не покажут и проблему опишут "а... караул...ничего не работает". Первые два пункта вы все-таки нормально прошли ;) Да еще и код вставили по человечески ;)
Ходит прекрастно,поиграюсь с расходами серв.Кому интерестно пишите, выложу фото или видео.
Ну так видео выложите.
> И тут вам нужно будет пойти посмотреть на пример "мигаем диодом без delay()", а также кучу подобных веток как работать со временем без delay()
Спасибо,веское замечание-учту.
Как новичек думал если поставлю delay() перед или после myserwo.write то эта пауза будет влиять только на данную серву а не на весь скетч
Максим видео ближе к вечеру
Как новичек думал если поставлю delay() перед или после myserwo.write то эта пауза будет влиять только на данную серву а не на весь скетч
К радости (или печали) в ардуино нет аспектно-ориентированного и декларативного программирования (без танцев с бубном). Только императивное. То есть каждый скетч - это просто пошаговая инструкция. И, в отличие от больших PC и старших версий микроконтроллеров - тут нет понятия потоков. Только один поток. То есть скетч выполняется пошагово. И только один шаг за раз. Никаких одновременностей - не бывает.
delay - фунция общего назначения. Не специально "серво-оринтированная", следовательно про сервы - она ничего не знает. Ее задача "остановить скетч на какое-то время". С сервами он или нет. Пример - базовый Мигаем светодиодом | Аппаратная платформа Arduino
Все функции условно можно разделить на "блокирующие" и "не блокирующие".
Блокирующие это которые останавливают (блокируют) скетч на время своего исполнения (и это время - ощутимо). Не блокирующие - это которые стараются выполнится как можно быстрее и передать управление дальше (таких большинство).
Примеры блокирующих - delay(), pulseIn(), стандартная библиотека stepper и т.п.
Не блокирующие - математические, servo.write, analogWrite, библиотека acelStepper и т.п. (вообщем все остальные)
Servo.write занимается тем, что побыстрому выставляет на пин какой-то PWM и передает управление дальше. Скетч пошел выполнять следующие команды. А сама серва крутится в этот момент, пытается занять положение указаное PWM-мом. Так как она не может сделать это моментально - это занимает какое-то время.
Тут у нас возникает как-бы одновременность. Скетч уже занимаетеся чем-то своим, а серва в этот момент крутитися и PWM генерируется. Но эта одновременность существует только за счет того что задачи PWM и вращение выплняются отдельными аппаратными блоками, а не основным ядром контроллера. Тот только "дал им указание".
Если мы в момент вращения сервы сделаем новые servo.write, то серва пойдет уже к новому положению, забудет про "старую команду", даже если еще не успела выполнить ее до конца. "Отставить, новый курс..."
Вернемся к вашей задаче. Итак стандартная servo.write - не блокирующая (к счастью, часто именно это и нужно), но вам потребовалась - блокирующая. Которая гарантирует что на серву не поступит новая команда (или команда для другой сервы) отменяющая предыдущую. Которая заставит скетч стоять на месте пока серва не станет в указанное положение . Для этого ее приходится комбинировать Servo.write с блокирующим delay(), выдавать всегда пару write/delay. Первое - команда, второе - ждать минимально необходимое время что-бы выполнить комаду прежде чем идти дальше.
Чем точнее мы будем давать вот это "время ждать" - тем лучше. Если следаем его слишком маленьким - серва не будет успевать докручиватся до нужно положения до того как скетч пойдет дальше, если слишком большим - мы будет видеть это как "остановки ненужные". Серва выкрутилась на какой-то угол и стоит ждет непонятно чего. Поэтому и желательно рассчитывать это время исходя из того на какой угол нам нужно повернуть серву (разницу между текущим и желательным положением), а не "забивать задержки прямо в код".
Другим подходом может быть - организация обратной связи от сервы. Ставить какие-то концевики, энкодер и т.п. - что-то что позволит узнать текущие РЕАЛЬНОЕ положение сервы. То есть работать по принципу - дали команду на серву, а потом крутимся в каком-то цикле, ждем пока наши сенсоры не доложат что серва заняла указанное положение и можно идти дальше. Такое решение будет намного более точным и менее подвержено влиянию температуры, качеству акума (если он просел - серва будет крутится медленее), но... сильно сложней как програмно, так и аппаратно, так что редко используется, особенно в домашних поделках. Бывают еще сервы которые уже имеют встроенный энкодер и могут сами доложить о своем настоящем положении, но... цена.
Кстати, раз вспомнил о шаговиках, то они тоже могут быть альтернативой в вашей задаче. Родная библиотека как раз "блокирующая". Пока он не выполнит указанное количество шагов - скетч дальше не пойдет. Но встанет вопрос о том "в какой позиции" он стоит при включении контроллера. Какую-то обратную-связь концевик, хотя-бы для нулевого положения прийдется городить. Зато крутится можем 360 град. И как правило шаговики менее мощны чем сервы (хотя за деньги конечно можно и силачей найти).
Видео с телефона,качество не ахти https://www.youtube.com/watch?v=AN45zEM9Z9Q
Нормальное качество. Чай не студийная съемка. И робот "симпатяжка". По доброму выглядит :)
Вы молодец. Видно что руки из нужного места растут (эх, а у меня логику - могу, а механику - обе руки левые :)
А вот этот его "ход по кругу", из-за движения ногами когда задняя серва в среднем положении, это "так задуманно" или "так вышло"?
Хорош цыплёнок ;)
И "музыка" звука достаточно забавная.
Зачёт!
Теперь всё это рихтовать, допиливать, донастраивать, эхх.. Удачи!
Конечно так вышло,надо коректировать углы и время поворота серв.
Вот видео на РУ,конечно поболее степеней свободы,плюс возможность танца что то типа степа.И понять динамику работы было попроще.
http://www.youtube.com/watch?v=AR_nRaI6OdU&feature=youtu.be
Собрать его особых проблем не было,благо стеклотекстолит двухсторонний,легко обрабатывается и быстро паяется.Да и возможность переделки на "ходу" тоже играет большую роль,что-то подрезать,где-то изменить угол крепления.Сами ноги от первоначального прототипа были укорочены на 4-5 см.Увеличена полосками площать стопы
Супер!!!!! Офигенно!!! Наверное первый робот которого мне захотелось повторить (хотя - руки не дойдут, но ведь - захотелось).
Если посчтитать дробь "возможности поделить на сложность" - думаю ваша платформа может дать фору многим заводским решениям за сотни (тысячи) баксов. Делать "просто" - это сложно, не каждому дано :) У вас - получилось.
Добрый день!
Подскажите плиз, что означает эта часть кода
{
16
Tuda(myservo1, 1);
17
Tuda(myservo2, 1);
18
Obratno(myservo1, 1);
19
Obratno(myservo2, 1);
20
Tuda(myservo1, 0);
21
Tuda(myservo2, 0);
22
Obratno(myservo1, 0);
23
Obratno(myservo2, 0);
24
}
Все проще, тебе нужно создать 2 мпеременные и прописывать их в сервы+ написать код для изменения этих переменных. Вот тут есть целый диплом с похожей темой