roboforum.ru

Технический форум по робототехнике.

Подскажите с кодом

Как собрать и запрограммировать робота на Arduino(Freeduino, Roboduino, Seeduino ...). Используем Wiring и Processing.

Подскажите с кодом

Сообщение kirill92 » 27 янв 2014, 16:10

Добрый день!
Я достаточно недавно начал заниматься программированием Arduino, и попробовав все простые примеры решил сделать что то свое. Мой взгляд остановился на манипулятора. Под рукой оказалась всего 4 сервы SG90. Поэтому движения у нас следующие: поднимаем, опускаем, поворот лево/право и соответственно захват и отпустить.
Написал вот такой скетч (захват клешни пока не написан):
Код: Выделить всёРазвернуть
#include <Servo.h>

Servo ser1; // серва 1
Servo ser2; // серва 2
Servo ser3; // серва 3
Servo ser4; // серва 4

byte pos = 0; // позиция сервы 1
byte pos2 = 0; // позиция сервы 2
byte pos3 = 0; // позиция сервы 3
byte pos4 = 0; // позиция сервы 4

const byte buttonPin1 = 8; // порт для кнопки вверх серва 1
const byte buttonPin = 12; // порт для кнопки вниз серва 1
const byte buttonPin2 = 7; // порт кнопки вправо серва 2
const byte buttonPin3 = 4; // порт кнопки влево серва 2
const byte buttonPin4 = 3; // порт кнопки захват сервы 3,4
const byte buttonPin5 = 2; // порт кнопки отпустить сервы 3,4

byte buttonState; // кнопка 1 серва 1 (вниз)
byte buttonState1; // кнопка 2 серва 1 (вверх)
byte buttonState2; // кнопка 3 серва 2 (вправо)
byte buttonState3; // кнопка 4 серва 2 (влево)
byte buttonState4; // кнопка 5 серва 3,4 захват
byte buttonState5; // кнопка 6 серва 3,4 отпустить

void setup ()
{
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
}

void loop ()
{
  buttonState = digitalRead (buttonPin);
  buttonState1 = digitalRead (buttonPin1);
  buttonState2 = digitalRead (buttonPin2);
  buttonState3 = digitalRead (buttonPin3);
  buttonState4 = digitalRead (buttonPin4);
  buttonState5 = digitalRead (buttonPin5);
 
  if (buttonState == HIGH) // опускаем
  for(pos = 1; pos < 80; pos += 1) 
  { 
    ser1.attach(9);   
    ser1.write(pos);         
    delay(20);
    ser1.detach();
    break;
  }
 
if (buttonState1 == HIGH) // поднимаем
for(pos = 80; pos > 1; pos-=1) 

    ser1.attach(9);
    ser1.write(pos);               
    delay(20);
    ser1.detach();
    break;               
}

   if (buttonState2 == HIGH) // поворот влево
   for(pos2 = 1; pos2 < 180; pos2 += 1) 
  { 
    ser2.attach(11);   
    ser2.write(pos2);           
    delay(20);
    ser2.detach();
    break;
  }
   if (buttonState3 == HIGH) // поворот вправо
   for(pos2 = 180; pos2 > 1; pos2 += 1) 
  { 
    ser2.attach(11);   
    ser2.write(pos2);           
    delay(20);
    ser2.detach();
    break;
  }
}
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение Aseris » 27 янв 2014, 16:57

А о чем вопрос?
Аватара пользователя
Aseris
 
Сообщения: 1142
Зарегистрирован: 01 сен 2009, 14:58
Откуда: Чехия
прог. языки: C/С++, VHDL, Verilog, ASM, Python

Re: Подскажите с кодом

Сообщение boblan » 27 янв 2014, 17:02

я конечно ни с Arduino ни с сервами неработал, поэтому не понимаю зачем полный цикл, но вот последний будет работать странно..
Код: Выделить всёРазвернуть
   if (buttonState3 == HIGH) // поворот вправо
   for(pos2 = 180; pos2 > 1; pos2 += 1) 
  { 
    ser2.attach(11);   
    ser2.write(pos2);           
    delay(20);
    ser2.detach();
    break;
  }
}

pos2 будет менятся от 180 до 255
boblan
 
Сообщения: 14
Зарегистрирован: 31 окт 2013, 01:04
Откуда: Великий Новгород
прог. языки: Delphi

Re: Подскажите с кодом

Сообщение Angel71 » 27 янв 2014, 18:58

да без разницы, что там и как в этом цикле меняется. сервам нужно постоянно импульсы подавать, с подобным кодом ничего хорошего в принципе не может быть.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Подскажите с кодом

Сообщение kirill92 » 28 янв 2014, 17:20

я конечно ни с Arduino ни с сервами неработал, поэтому не понимаю зачем полный цикл, но вот последний будет работать странно..

Ошибку нашел, код переделал. Вопрос в том как его правильно оформить, и как лучше написать продолжение для того чтобы захват работал (одновременно 2 сервы).

Код: Выделить всёРазвернуть
 /* Рука манипулятор, с движениями вверх, вниз, поворотом манипулятора и захватом предметов. Работает на 4 сервоприводах с кнопочным управлением. */

#include <Servo.h>

Servo ser1; // серва 1
Servo ser2; // серва 2
Servo ser3; // серва 3
Servo ser4; // серва 4

byte pos = 0; // позиция сервы 1
byte pos2 = 0; // позиция сервы 2
byte pos3 = 0; // позиция сервы 3
byte pos4 = 0; // позиция сервы 4

const byte buttonPin1 = 8; // порт для кнопки вверх серва 1
const byte buttonPin = 12; // порт для кнопки вниз серва 1
const byte buttonPin2 = 7; // порт кнопки вправо серва 2
const byte buttonPin3 = 4; // порт кнопки влево серва 2
const byte buttonPin4 = 3; // порт кнопки захват сервы 3,4
const byte buttonPin5 = 2; // порт кнопки отпустить сервы 3,4

byte buttonState; // кнопка 1 серва 1 (вниз)
byte buttonState1; // кнопка 2 серва 1 (вверх)
byte buttonState2; // кнопка 3 серва 2 (вправо)
byte buttonState3; // кнопка 4 серва 2 (влево)
byte buttonState4; // кнопка 5 серва 3,4 захват
byte buttonState5; // кнопка 6 серва 3,4 отпустить



void setup ()
{
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
 
  ser1.attach(9);
  ser2.attach(11);
}



void loop ()
{
  buttonState = digitalRead (buttonPin);
  buttonState1 = digitalRead (buttonPin1);
  buttonState2 = digitalRead (buttonPin2);
  buttonState3 = digitalRead (buttonPin3);
  buttonState4 = digitalRead (buttonPin4);
  buttonState5 = digitalRead (buttonPin5);
 
if (buttonState == HIGH) // опускаем
int up = up_down1 ();
 
if (buttonState1 == HIGH) // поднимаем
int down = up_down2 ();

if (buttonState2 == HIGH) // поворот влево
int left = go_left ();

if (buttonState3 == HIGH) // поворот вправо
int right = go_right ();
}

int up_down1 ()
{
  for(pos = 1; pos < 80; pos += 1) 
  {   
    ser1.write(pos);         
    delay(20);
    return 0;
  }
}

int up_down2 ()
{
  for(pos = 80; pos > 1; pos-=1) 

    ser1.write(pos);               
    delay(20);
    return 0;   
}
}
 
int go_left ()
{
   for(pos2 = 1; pos2 < 180; pos2 += 1) 
  {     
    ser2.write(pos2);           
    delay(20);
    return 0;
  }
}

int go_right ()
{
   for(pos2 = 180; pos2 > 1; pos2 -= 1) 
  {     
    ser2.write(pos2);           
    delay(20);
    return 0;
  }
}


да без разницы, что там и как в этом цикле меняется. сервам нужно постоянно импульсы подавать, с подобным кодом ничего хорошего в принципе не может быть.


Можно подробнее? Я сделал отключение серв для того чтобы не дребезжали.
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение Angel71 » 28 янв 2014, 18:03

можно :) только с начала внятно опишите, что хотите сделать и что именно не получается.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Подскажите с кодом

Сообщение kirill92 » 28 янв 2014, 21:15

1) Как иправить код чтобы сервы при простое не дребезжали? Я рассматривал изначально вариант каждый раз в цикле for прописывать ser.attach()..........ser.detach()....break;Для того чтобы при отпускании кнопки серва отключалась и оставалась в той позиции до какой успела повернуться.
2) Можно ли захват сделать таким образом:
If(...........)
{
for(........) - серва 1
{
....
}
for(..............) - серва 2
{
....
}
}
Если нет то как лучше? (Клещи у манипулятора на 2х сервах).
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение Angel71 » 28 янв 2014, 22:15

не особо что-то прояснилось. :) значит и нет смысла напрягаться, особо детально/доходчиво описывать и вытягивать клещами.
при отключении питания или прекращении подачи импульсов, вал сервы может вращаться под внешним воздействием. на сколько легко - это вопрос ушатанности "разработанности" механики и собственно механики самой сервы, а они по факту очень разные. "оставалась в той позиции" - это ни о чём. если она ничего не удерживает, это одно - отключили питание или прекратили подавать импульсы и всё. а если нужно что-то удерживать, так смотря какая механика у клешни, нюансы с сервой, что нужно удерживать и в каком положении. с дрожанием аналогично - смотря как дрожит и как именно хочется что бы не дрожала. может достаточно будет подать другое напряжение или попытаться в коде с импульсами поиграться или попробовать номиналы деталек на плате поменять, а может эти сервы на большее не способны, по крайней мере без замены электроники и/или потенциометра. так может их лучше сразу на другие заменить и не мучаться.
как в коде реализовать - это ситуационно, вариантов море. попробуйте допустим со своим кодом одновременно 2 кнопки нажать. хотя бы подумайте что будет и устраивает ли это вас.
вот один ленивый вариант:
1) опрос кнопок
2) вылавливаине дребизга при нажатии, если это нужно
3) вычисление значения положения для каждой сервы
4) установка значения положения для каждой сервы
5) топаем в п. 1
если нужно добавляйте проверку на изменение значения переменных, что бы лишний раз лишний код не дёргать. можно подобавлять проверку времени, что бы слишком часто что-то не делать. и т.д. в общем что добавить, выкинуть, поменять местами, объединить, разделить,... это сами думайте. вариант далеко не единственный и при определённых условиях легко может оказаться очень неудобным или не эффективным. абсолютно нет желания гадать, что именно у вас там не получается, что и как сейчас хотите сделать и тем более что в будущем захотите.
дальше наверно сами :) вытягивать клещами каждый нюансик, который может всё кардинально менять нет никакого желания.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Подскажите с кодом

Сообщение kirill92 » 29 янв 2014, 03:56

Спасибо за советы. Но у нас немного получается разговор глухого с немым. :)
1) Вопрос был четкий будет ли приведенный выше код работать для захвата 2-х серв?
2)Сервы слабенькие SG-90, соответственно ничего тяжелого поднимать не будут. Идею с тем что отключать не желательно понял.
3) Можно ли использовать break в цикле for для остановки вращения при отпускании кнопки (при нажатии положение будет считываться и серва поворачиваться дальше)?
4) Никакой механики у клешни, 2 захвата крепятся на 2 сервы и ВСЕ!
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение Angel71 » 29 янв 2014, 05:37

1) вопрос так не звучал. в последней реинкарнации "будет ли приведенный выше код работать для захвата 2-х серв" могу только шутя - кодом сервы не захватишь
2) "слебенькие" и "тяжелое" очень относительно. смотря какой предмет и конструкция клешни. на них вполне реально сделать захват, способный удерживать некоторые предметы с весом в несколько кг
3) икс вас знает, для какого именно кода цикла вы про брэйк спрашивает. можно сделать прерывание по условию, но что за условие вы напишите и что это вам даст
4) сервы 4, степени свободы 3. если под "никакой механики" подразумевалось что-то такое
1.png
1.png (32.04 КиБ) Просмотров: 2260

просто две каких пластинки на качалках :) ну... может и выживут
а если серьёзно, уже более-менее вырисовывается, что вы хотите и что не получается. икс с этим дрожанием - видео нет, что там с питанием серв непонятно. а для управления 4-мя сервами + что вы там ещё хотите делать, код на подобии того, что вы приводили выше мягко говоря очень плох. :) и вставите вы там в цикле(ах) брейк или нет, особо роли не играет.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Подскажите с кодом

Сообщение kirill92 » 29 янв 2014, 12:49

Питание от 4х батареек (было напрямую от ардуины).
Видео выложу.
Несколько КГ это многовато :) конструкция не выдержит. Так как для меньшего гемороя он собран из конструктора LEGO реквизированного у ребенка.
Да пока что 2 пластинки на качалках (это макет). Когда разберусь во всем уже можно и нормальный манипулятор сделать и клешню другую.
Чем плох код? :)
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение RootAdmin » 29 янв 2014, 13:36

Код ИМХО плох тем что не разделен процесс управления изменением значений и собственно генерация значений.
Я б писал так:

Инициализация таймера.
Лучше подобрать так чтоб весь счет таймера занимал 2000 мсек Если не точно все равно - считаем время тика, пригодится. Настраиваем на выхов прерывания по достижению установленного значения
Инициализация переменных, по одной для каждой сервы, даже лучше массивом. Одномерным, где 0 элемент - первая и так далее
int Servos[128,128,128]
int(или другой тип) Servostimer[XXX,XXX,XXX] //хранит длительность в тиках таймера
int step[1,1,1] //указатель на порядок обрабортки в таймере.
volatile int number=0; Номер текущей обрабатываемой сервы в таймере


Основной цикл
//Перебор номеров кнопок
фор i=0 то 2 (три кнопки "вверх")
Если кнопка нажата Servos[i]++
некст
фор i=3 то 5 (три кнопки "вниз")
Если кнопка нажата Servos[i-3]--
некст
Тут сортируем сервы чем угодно по длительности импульса (по возрастанию) и номера пишем в step[2,0,1] например и пересчитываем в массиве Servostimer значения
Конец основного цикла

Таймер(прерывание)
Если number==4 {Поднимаем все пины серв в "1" (начинаем генерацию импульсов для каждой сервы)
number=0; //обнуляем счетчик
Устанавливаем следующий вызов таймера на конец цикла (Количество тиков таймера на 2000 мсек)-Servostimer[0]-Servostimer[1]-Servostimer[2]
}
Иначе
{
если number>0 тогда {опускаем пин сервы step[number-1]} //Вот что меня глодало, поведение при обработке нулевого элемента. Так - правильно. Хоть и менее красиво.
если number<3 {Читаем Servostimer[step[number]] и пишем значение в счетчик для следующего вызова}
number++
}
конец таймера

Получается что таймер _постоянно__генерит_ импульсы сервам.
Длительность - можно менять кнопками.
Последний раз редактировалось RootAdmin 29 янв 2014, 15:58, всего редактировалось 1 раз.
Дым, идущий из всех устройств в помещении предвещает появление электрика.
RootAdmin
 
Сообщения: 1725
Зарегистрирован: 07 авг 2010, 21:29
Откуда: КМВ
прог. языки: C
ФИО: Андрей

Re: Подскажите с кодом

Сообщение kirill92 » 29 янв 2014, 14:39

Спасибо. Попробую.
kirill92
 
Сообщения: 8
Зарегистрирован: 01 окт 2013, 17:37

Re: Подскажите с кодом

Сообщение Angel71 » 29 янв 2014, 15:33

>> Чем плох код?
а чем он хорош? что именно вы тем циклом хотите сделать непонятно. в конце цикла у вас то break, то return. перед тем как их в цикле написать, вы хоть пробовали почитать что это такое? если переделаете циклы, что бы они не прерывались, так у вас каждая итерация цикла будет очень долго выполняться. при 80-ти итерациях, с задержкой в 20мс это будет 1600мс, т.е. почти 2 секунды. при 180-ти итерациях 3600мс. нажали на кнопку и проверка, нажата ли кнопка будет через ~2-4 секунды. так чем хорош такой код?
kirill92, то, что RootAdmin написал... так то оно так, только судя по вашему коду можете не потянуть. если не будет получаться, настойчиво рекомендую поставить на компьютере какую среду разработки и хоть немного подучить основы си. для простоты изучения лучше создавать просто консольные приложения.
Аватара пользователя
Angel71
 
Сообщения: 10668
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Подскажите с кодом

Сообщение RootAdmin » 29 янв 2014, 15:59

Можно и помочь. Для разминки ума просто нужно иногда писать что-то отвлеченное. А то OpenCV весь день разбирать - жуть...
Дым, идущий из всех устройств в помещении предвещает появление электрика.
RootAdmin
 
Сообщения: 1725
Зарегистрирован: 07 авг 2010, 21:29
Откуда: КМВ
прог. языки: C
ФИО: Андрей

След.

Вернуться в Arduino и другие Xduino

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13