Прерывание и сервы
- Войдите на сайт для отправки комментариев
Пнд, 25/06/2012 - 21:59
Есть две сервы управляемые потенциометрами и кнопками. Хочется одновременной работы серв. С потенциометрами всё нормально. А вот при движении серв в запомненное положение сначала движется одна , потом вторая. Почитал форум и гугл - нужны прерывания. А как и с чего начать не знаю. Выкладываю часть кода. Нужно при нажатии кнопки 7 обе сервы синхронно переводились в сохранённые положения, а при нажатии кнопки 8 возвращались обратно.
#include <Servo.h> #include <EEPROM.h> Servo myservo1; Servo myservo2; int button1Pin = 2; // save 1 int button2Pin = 3; // load 1 int button3Pin = 4; // motion 1 int button4Pin = 5; // save 2 int button5Pin = 6; // load 2 int button6Pin = 7; // motion 2 int button7Pin = 8; // load 1-2 int button8Pin = 11; // motion 1- 2 int inputMode1 = 1; int inputMode2 = 1; int val; int val2; int button1State; int button2State; int button3State; int button4State; int button5State; int button6State; int button7State; int button8State; int pot1pin = 0; int pot2pin = 0; int val3; int val4; int addr = 0; byte value; int pos = 0; void setup() { pinMode(button1Pin, INPUT); pinMode(button2Pin, INPUT); pinMode(button3Pin, INPUT); pinMode(button4Pin, INPUT); pinMode(button5Pin, INPUT); pinMode(button6Pin, INPUT); pinMode(button7Pin, INPUT); pinMode(button8Pin, INPUT); myservo1.attach(9); myservo2.attach(10); Serial.begin(9600); } void loop(){ if(inputMode1) { val3 = analogRead(pot1pin); val3 = map(val3, 0, 1023, 0, 179); myservo1.write(val3); delay(15); } if(inputMode2) { val4 = analogRead(pot2pin); val4 = map(val4, 0, 1023, 0, 179); myservo2.write(val4); delay(15); } if(button1State == HIGH) { // button 1 save1 EEPROM.write(addr, val3); EEPROM.write(25, 1); delay(100); } if(button2State == HIGH && EEPROM.read(25) == 1) { // button 2 load1 inputMode1=0; value = EEPROM.read(addr); delay(100); for(pos = val3; pos < value; pos += 1) { myservo1.write(pos); delay(30); } for(pos = val3; pos > value; pos-=1) { myservo1.write(pos); delay(30); } } if(button4State == HIGH) { // button 3 motion1 inputMode1=1; for(pos = value; pos < val3; pos += 1) { myservo1.write(pos); delay(50); } for(pos = value; pos > val3; pos-=1) { myservo1.write(pos); delay(50); } } if(button5State == HIGH) { // button 4 save2 EEPROM.write(addr, val4); EEPROM.write(55, 1); delay(100); } if(button6State == HIGH && EEPROM.read(55) == 1) { // button 5 load2 inputMode2=0; value = EEPROM.read(addr); delay(100); for(pos = val4; pos < value; pos += 1) { myservo2.write(pos); delay(30); } for(pos = val4; pos > value; pos-=1) { myservo2.write(pos); delay(30); } } if(button8State == HIGH) { // button 6 motion2 inputMode2=1; for(pos = value; pos < val4; pos += 1) { myservo2.write(pos); delay(50); } for(pos = value; pos > val4; pos-=1) { myservo2.write(pos); delay(50); } } if(button7State == HIGH && EEPROM.read(25) == 1, EEPROM.read(55) == 1) { //load 1-2 inputMode1=0; inputMode2=0; value = EEPROM.read(addr); for(pos = val3; pos < value; pos += 1) { myservo1.write(pos); delay(30); } for(pos = val3; pos > value; pos-=1) { myservo1.write(pos); delay(30); } for(pos = val4; pos < value; pos += 1) { myservo2.write(pos); delay(30); } for(pos = val4; pos > value; pos-=1) { myservo2.write(pos); delay(30); } } if(button8State == HIGH) { // motion 1-2 inputMode1=1; inputMode2=1; for(pos = value; pos < val3; pos += 1) { myservo1.write(pos); delay(50); } for(pos = value; pos > val3; pos-=1) { myservo1.write(pos); delay(50); } for(pos = value; pos < val4; pos += 1) { myservo2.write(pos); delay(50); } for(pos = value; pos > val4; pos-=1) { myservo2.write(pos); delay(50); } } }
Может кто то поможет?
Внутренние или наружные прерывания, какие таймеры использовать, пример кода.
Я думаю, прерывания вам не помогут.
Ибо для стоящей перед вами задачи они не нужны.
Требуется изменение подхода к решению проблемы движения двух сиервоприводов.
Как вы делаете сейчас? Отрабатываете ПОЛНОЕ движение одной сервой, затем ПОЛНОЕ движение другой. В двух циклах:
а надо в одном:
как-то так ...
А зачем вообще эти микрошаги? В постановке задачи цели "снизить скорость серв" - не упоминалась. А без этого можно сразу серве говорить "конечную позицию". И она пойдет крутится. В отличие от степпера серва не блокирует поток. Мы выдали pwm а дальше она сама пытается достичь с ним равновесия.
Вообщем тут случай когда "мудрение" во вред.
А зачем вообще эти микрошаги? В постановке задачи цели "снизить скорость серв" - не упоминалась. А без этого можно сразу серве говорить "конечную позицию". И она пойдет крутится.
Обычно оно так. Но на практике есть механика, которая имеет массу, чтобы не расшатывать механику, снижают скорость, если снижение нежелательно, делают ускорение/торможение. IMHO.
А зачем вообще эти микрошаги? В постановке задачи цели "снизить скорость серв" - не упоминалась. А без этого можно сразу серве говорить "конечную позицию". И она пойдет крутится. В отличие от степпера серва не блокирует поток. Мы выдали pwm а дальше она сама пытается достичь с ним равновесия.
Вообщем тут случай когда "мудрение" во вред.
Запоминание позиций серво
Я бы делал так:
Выкинул нафиг val4, писал в память именно val3. В том виде какое оно получается после применения функции map, тогда при чтении с ним тоже ничего мудрить не нужно. Достал и, как есть, отправил на серву.
Скорость сервы делал бы так: завел переменную в которую запоминаю "где сейчас серва". Когда нужно повернуть в новую позицию - вычисляем разницу между нужным положением, и текущим. И поворачиваем "по чуть-чуть", с паузами. Например сечас она на 20-ти, а нужно 50. Значит даем командау 25, пауза, 30, пауза, 35, пауза, 40, пауза, 45, пауза, 50. При достаточно малом шаге и небольших паузах - будет эффект плановсти движение. Неторопливого.
Вообщем примерно так:
И везде в скетче, вместо myServo.write, дальше используем setServo(...) если нужно быстро установить значение сервы и setServoSlow() если медленно.
SERVO_STEP, и STEP_DELAY - подбираем на глаз. Что-бы была медленность, но не было видимой "дергнанности"
2Maksim: а чем смысл цитат? Пытаетесь подловить на противоположных высказываниях? Не вышло :)
А зачем вообще эти микрошаги? В постановке задачи цели "снизить скорость серв" - не упоминалась.
Тут ставилась задача "одновременности вращения", а в той ветки человек хотел "снизить скосроть". Логично что для разных задач используются разные решения? Микрошаги еще могут потребоваться если нужно что-бы сервы выходили на заданную позицию одномоментно. Даже если одной, для этого, нужно повернутся на 90 градусов, а другой на 5-ть.
Но, обычно, стараются не усложнять задачу до тех пор пока "по другому никак". Так что если можно обойтись без микрошагов, пока нет 100% уверенности в их необходимости - лучше обойтись.
Кстати даже с микрошагами, в коде который привел step62, сообщение #1, второй скетч. delay тоже можно сделать "общим", что-бы они крутились "ну вообще одновременно".
Микрошаги нужны (сейчас соберу схему и попробую в одном цикле) .
Просто напомнить, что проэкт тот же.
Микрошаги нужны (сейчас соберу схему и попробую в одном цикле) .
Вы, в стартовом посте употребили слово "синхронно". Имелось ввиду "просто могут крутится одновременно" или "должны начать и ЗАКОНЧИТЬ" движение одновременно?
И еще сервы поворачиваются занимают одну и ту же позицию или возможны ситуации когда "одна поворачивается с 10 до 40, а другуя с 30 до 180"?
Сервы поворачиваются на разные углы (каждая в зависимости от сохранённого положения и настоящего) и в любом направлении (по часовой стрелке, против, навстречу друг другу).
Мне нужно их одновременное начало движения и одновременное окончание, но об этом я просто "не заикался", т.к. пока не могу их просто заставить одновременно двигаться. Перепробовал уже кучу вариантов- результат никакой.
Попробуйте вот такой скетч:
На нем сервы движутся одновременно?
Да, сервы движутся одновременно.
В моём случае нужно одновременно прочитать из памяти запомненные положения серв и одновременно перевести их в эти положения.
Ну... так в чем затруденение? Читайте два значения, делай два myservoX.write(NewValueX); И только потом общий, для них обоих, delay(X). Главное не втыкать делей между servo1.write и servo2.write и будут они одновременно ехать.
В сообщении #2 я же уже писал про это.
Или пример из предыдущего посмотрите
вместо 0 и 180, подставте прочитанные из памяти значения - вот и пойдут они одновременно поворачиватся.
Другое дело что остановятся не обязательно одновременно. Но это уже следующий этап, тут уж "микрошаги" вкручивать" нужно будет.
Вот функция для кручения двух серв синхронно микрошагами. Начинаю и "кончают" одновременно.
Не получается . Всё равно движение по очереди.
> Всё равно движение по очереди.
ну если вы крутите их по очереди, то естественно они и крутятся по очереди. Вы не добились одновременно движения, а уже полезли в микрошаги (которые как было сказанно будут следующим этапом).
По вашему коду, вы вналчае пробежались по всем шагам для первой сервы (и естественно в этот момент она начала крутится), ПОТОМ по всем шагам для второй. Я уже три примера дал где между myservo1.write и myservo2.write ничего нет. Если вы хотите одновременонсти, так и выдавайте команды на поворот одновременно.
Выкинте все после одинадцаттой строчки, в десятой поправте myservo1 на myservo2 и в 11-той можете увеличить delay что-бы обе точно успели довернутся. Убедитесь что они поворачиваются одновременно, в значения прочитанные из памяти. А уж потом танцуйте дальше (скорость, синхронность и т.п.) Раз не получается - идите инкрементными шагами. Не нужно сразу все пытаться сделать и крутить одновременно, и память читать, и кнопки обрабатывать....
Вначале одновременно закрутили, потом то же самое но прочитанное из памяти, потом то же самое но читать из памяти по кнопке..., потом "снизить скорость""
P.S. И выше я уже дал готовую функцию которую можно использовать.
ну если вы крутите их по очереди, то естественно они и крутятся по очереди.
По вашему коду, вы вналчае пробежались по всем шагам для первой сервы (и естественно в этот момент она начала крутится), ПОТОМ по всем шагам для второй.
Кстати ровно о том же вам говорил STEP962 много постов назад.
Как вы делаете сейчас? Отрабатываете ПОЛНОЕ движение одной сервой, затем ПОЛНОЕ движение другой.
Но вы почему-то проигнорировали его пост.
Я думаю, прерывания вам не помогут.
Ибо для стоящей перед вами задачи они не нужны.
Требуется изменение подхода к решению проблемы движения двух сиервоприводов.
Как вы делаете сейчас? Отрабатываете ПОЛНОЕ движение одной сервой, затем ПОЛНОЕ движение другой. В двух циклах:
а надо в одном:
как-то так ...
Я этот вариант сразу попробовал, но не работает. Может я что то напутал.
>Я этот вариант сразу попробовал, но не работает. Может я что то напутал.
Может. Но о том что вы пробовали и как выглядели результаты попытки вы предпочли сохранить в тайне. Видимо что-бы никто не догадался.
Его код выглядит, вообщем-то рабочим (если только вы не добавили, при пробе, к нему все что только возможно. И чтение, и кнопки и т.п.). Но даже если он где-то чуток ошибся в коде, текстом он вам вполне правильно объяснил ошибочность вашего подхода. А вы потом повторяли опять ту же самую ошибку.
P.S. И кстати вы, не всегда, но довольно частно, наступаете на одни и те же грабли. Вам дают какой-то код, а вы либо просто отмалчиваетесь/игнорируете, либо говорите "не работает" и ждете пока вас переспросят подробности (а ведь могут и не переспросить, а просто забить). Так вы резко понижаете шансы того что кто-то сможет вам помочь. Хорошо что хоть код который запускать пробовали уже начали давать без намека :)
В варианте STEP962 у меня всё зависло. Но его подход я понял и спасибо ему за это. Мне как чайнику просто тяжело многие вещи реализовать
Адаптировал код leshak из поста #13 - заработало!!!! Спасибо за помощ.