Программа робота для поворота при обнаружении припятствия

Russk1j
Offline
Зарегистрирован: 03.05.2012

Здравствуйте, подскажите пожалуйста как реализовать программу, при который робот при обнаружении препятствия изменял курс движения.

При моей программе он почему-то долго соображает что перед ним что-то есть (оклоло 2-3 секунд) хотя датчик обновляется раз 5 в секунду.

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

Датчик у меня ультразвуковой HC-RS04, который вращается на серве. И можно ли сделать так, что бы робот объезжал предмет. Т.е. в зависимости от того на какой угол повернута серва и при значении, что показание с датчика будет меньше 20 он уже будет поварачивать соответственно. Например в момент поворота сервы на угол при котором серва смотрит влево и показании датчика меньше 20 робот проедет немного вправо, и наоборот. И вообще серва наверно не сможет отослать сигнал в каком она положении, т.е. нужен шаговик?

Есть вот такой шаговик ST28

Как вот по этой ссылке в самом низу, он сможет отослать сигнал о своем положении, или он только тоже поворачивает на заданный угол?

http://freeduino.ru/arduino/mshield.html

#include <Servo.h>
#include <AFMotor.h>
Servo LexaServo;
int servoPin = 9;
AF_DCMotor motor1(1); //правый
AF_DCMotor motor2(2); //Левый 

const int Trig = 2; 
const int Echo = 12; 

void setup()
{
  pinMode(Trig, OUTPUT); 
  pinMode(Echo, INPUT); 
  LexaServo.attach(servoPin);
  Serial.begin(9600); 
}

unsigned int time_us=0;
unsigned int distance_sm=0;

 void loop()
{
  {
  for (int i=40; i<=120; i=i+10)  // от 40 до 120 градусов
   {                          
    LexaServo.write(i);       // говорим серве куда идти
    delay(200); 
    digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
   // delayMicroseconds(10); // Удерживаем 10 микросекунд 
    digitalWrite(Trig, LOW); // Затем убираем 
    time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
    distance_sm=time_us/58; // Пересчитываем в сантиметры
 
    Serial.println(distance_sm); // Выводим на порт
  }
 }   
    if (distance_sm<20) // Если расстояние менее 20 сантиметром 
    { 
      motor1.run(FORWARD);
      motor2.run(BACKWARD);
     
      motor1.setSpeed(254);
      motor2.setSpeed(254);     
    } 
    else 
    { 
      motor1.run(FORWARD);
      motor2.run(FORWARD);

      motor1.setSpeed(254);
      motor2.setSpeed(254);
    }
}


 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Russk1j пишет:
И вообще серва наверно не сможет отослать сигнал в каком она положении, т.е. нужен шаговик?
А вы думаете шаговик может отсылать данные о своем положении? А зачем это надо? Вы задали угол, серва отработала этот угол, что еще вам нужно для того что бы знать где находится серва?

Russk1j пишет:
При моей программе он почему-то долго соображает что перед ним что-то есть (оклоло 2-3 секунд) хотя датчик обновляется раз 5 в секунду.

Это потому что у вас 120 циклов с задержкой по 200 миллисекунд.

Вот может, что-то полезное там найдете Робот "Объезжайка-1"

Russk1j
Offline
Зарегистрирован: 03.05.2012

Спасибо, посмотрю.
А как тогда отделить цикл сервы, там в любом случае мне задержка нужна?
И как сделать чтоб движки вращались определенное время? Какая функция нужна?
 

PS классный робот), а у меня только УЗ дальнометр

maksim
Offline
Зарегистрирован: 12.02.2012

>>> А как тогда отделить цикл сервы, там в любом случае мне задержка нужна?
Задержка нужна, решается это так Мигаем светодиодом.

>>> И как сделать чтоб движки вращались определенное время?
Значением ШИМа подаваемым на двигатель я регулировал усилие/обороты двигателей, тем самым менял траэкторию движения. Но можно и временем работы двигатей изменять траэкторию, это уже как вам больше нравится.

>>> а у меня только УЗ дальнометр
Без разницы чем сканировать пространство.

leshak
Offline
Зарегистрирован: 29.09.2011

 

Russk1j пишет:

 

Спасибо, посмотрю.
А как тогда отделить цикл сервы, там в любом случае мне задержка нужна?

Самой серве - задержка не нужна. Вы дале ей команду "занять положение" и дальше можете заниматся своими делами. Крутится она будет сама. Сама и остановится, когда займет "скомандованное" положение.
Задеркжа становится нужна, когда дальнейшая логика подразумевает что серва "уже стоит в новом положении".
Но опять-таки использовать задержку для этого - лобовой и не самый лучший путь (она останавлиавет скетч и сбивает все "паралельные" процессы).
Гораздо лучше "влючили серву", "запомнили время когда мы это сделали", а потом, регулярно смотрим на часы "прошло ли достаточно времени" с момента включения сервы.

Примерно так:

.....
unsigned long servoOnTime=0;
..
void loop(){
  if(УСЛОВИЕ_ПРИ_КОТОРОМ_НУЖНО_ПОВЕРНУТЬ_СЕРВУ){
     myServo.write(newPos); // командуем занять новую позицию
     servoOnTime=millis(); // запомнили когда дали команду серве
     
  };
  
  if( 
      servoOnTime // если  "идет отсчет времени поворота сервы
      &&   ( (millis()-servoOnTime)>ВРЕМЯ_ДОСТАТОЧНОЕ_ДЛЯ ПОВОРОТА) // и прошло достаточно времени
     ){
       ...
       // КОД который нужно выполнить когда серва займет новую позицию
       servoOnTime=0; // выключили отсчет времени поворота, что-бы "КОД который нужно" выполнился только один раз
    }
  
  .....
  // КАКОЙ-ТО код который нуйжно выполнять одновременно с кручением сервы
  // желательно что-бы он тоже был без delay(), pulseIn и т.п. что может остановить скетч на продолжительное время
  .....  
}

 

Russk1j пишет:

И как сделать чтоб движки вращались определенное время? Какая функция нужна?


Зайдите в раздел "Программирование" и посмотрите примиер "Мигаем диодом без delay()"

 

Russk1j
Offline
Зарегистрирован: 03.05.2012

 Спасибо, буду разбираться.
А как можно посмотреть через сам процессинг диаграмму при сканировании пространства, т.е. как тут
http://we.easyelectronics.ru/part/eksperimenty-s-uz-dalnomerom-proekt-vy...
 

Russk1j
Offline
Зарегистрирован: 03.05.2012

maksim пишет:

Russk1j пишет:
И вообще серва наверно не сможет отослать сигнал в каком она положении, т.е. нужен шаговик?
А вы думаете шаговик может отсылать данные о своем положении? А зачем это надо? Вы задали угол, серва отработала этот угол, что еще вам нужно для того что бы знать где находится серва?

У меня просто была такая задумка:

Робот едет, датчик снимает показания расстояния, серва вращает датчик на угол градусов 60 туда/обратно, не много, чтобы только видеть перед собой что находится. Все нормально препятствия нет.
Как только что-то появляется, т.е. в какой-то момент времени серва находится например в левом положении при каком-то угле и значение датчика показывает меньше 20, т.е. нужно поворачивать, и тут как раз в зависимости куда смотрит серва, в противоположную сторону подвернуть роботу чтобы не врезаться. Как то так

leshak
Offline
Зарегистрирован: 29.09.2011

 

Russk1j пишет:

 

Спасибо, буду разбираться.
А как можно посмотреть через сам процессинг диаграмму при сканировании пространства, т.е. как тут
http://we.easyelectronics.ru/part/eksperimenty-s-uz-dalnomerom-proekt-vy...

Открывать туториалы по процессингу. Научится на нем что-нибудь присовть програмно. Научится в нем общатся с радуиной через Serial. Ну а дальше "все просто". Ардуиной отсылаем в Serial положение сервы и показания сонара, в процессинге читаем и в соотвествии с полученынми данными, с помощью drawLine, drawBox и т.п. рисуем диаграмму.
Возможно, для этого, прийдется еще и школьную немного геометрию повсмоинать. ЧТо такое синус и косинус :) Как найти координаты отрезка, если известны координаты одного конца (центр экрана), его длина (показания сонара), и угол поворота относительно оси координат (положение сервы). дальше drawLine с высчитаными координатами и дело в шляпе :)

 

leshak
Offline
Зарегистрирован: 29.09.2011

Russk1j пишет:

У меня просто была такая задумка:

Попробуйте поискать на форуме. Месяц-два назад. Ну просто "один в один" задачу решали (не помню чем закончилось).

Russk1j
Offline
Зарегистрирован: 03.05.2012

leshak пишет:

 

Russk1j пишет:

 

Спасибо, посмотрю.
А как тогда отделить цикл сервы, там в любом случае мне задержка нужна?

Самой серве - задержка не нужна. Вы дале ей команду "занять положение" и дальше можете заниматся своими делами. Крутится она будет сама. Сама и остановится, когда займет "скомандованное" положение.
Задеркжа становится нужна, когда дальнейшая логика подразумевает что серва "уже стоит в новом положении".
Но опять-таки использовать задержку для этого - лобовой и не самый лучший путь (она останавлиавет скетч и сбивает все "паралельные" процессы).
Гораздо лучше "влючили серву", "запомнили время когда мы это сделали", а потом, регулярно смотрим на часы "прошло ли достаточно времени" с момента включения сервы.

Примерно так:

.....
unsigned long servoOnTime=0;
..
void loop(){
  if(УСЛОВИЕ_ПРИ_КОТОРОМ_НУЖНО_ПОВЕРНУТЬ_СЕРВУ){
     myServo.write(newPos); // командуем занять новую позицию
     servoOnTime=millis(); // запомнили когда дали команду серве
     
  };
  
  if( 
      servoOnTime // если  "идет отсчет времени поворота сервы
      &&   ( (millis()-servoOnTime)>ВРЕМЯ_ДОСТАТОЧНОЕ_ДЛЯ ПОВОРОТА) // и прошло достаточно времени
     ){
       ...
       // КОД который нужно выполнить когда серва займет новую позицию
       servoOnTime=0; // выключили отсчет времени поворота, что-бы "КОД который нужно" выполнился только один раз
    }
  
  .....
  // КАКОЙ-ТО код который нуйжно выполнять одновременно с кручением сервы
  // желательно что-бы он тоже был без delay(), pulseIn и т.п. что может остановить скетч на продолжительное время
  .....  
}

 

Если я правильно понял, то код должен выглядить следующим образом, еслия только сервой управляю и все:

#include <Servo.h>
Servo myServo;
int servoPin = 9;
void setup()
{
  LexaServo.attach(servoPin);  
}
unsigned long servoOnTime=0;

void loop(){
  if(int i=40; i<=120; i=i+10)
  {
     myServo.write(i); // командуем занять новую позицию
     servoOnTime=millis(); // запомнили когда дали команду серве
     
  };
  
  if(servoOnTime &&   ( (millis()-servoOnTime)>2000) // и прошло достаточно времени
     ){
       millis()=servoOnTime;
       servoOnTime=0; // выключили отсчет времени поворота, что-бы "КОД который нужно" выполнился только один раз
    }
  
}

Только не компилируется, поправьте пожалуйста. Еще плохо разбираюсь.

Где в коментарии вы писали время, достаточное для поворота "ВРЕМЯ_ДОСТАТОЧНОЕ_ДЛЯ ПОВОРОТА"

это время промежутков между поворотом в 10 градусов, или это полный цикл сервы?

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

Russk1j пишет:

 

Только не компилируется, поправьте пожалуйста. Еще плохо разбираюсь.

Не обижайтесь, но принципиально даже смотреть код не буду. Раз "не компилируется", значит выдает какую-то ошибку. Почему ее не сообщить тут, что-бы гадать не приходилось? К тому же прочитав эту ошибку очень не нулевая вероятсно что и сами поймете в чем проблема. Написание кода на 80% и состоит в попытках объяснить "че ты хочешь" компилятору, а он пытается сказать "что ему не нравится".

Вообщем как максимум - попытайтесь сами понять что оно хочет (можно со словариком), как минимум - копипастайте сюда ошибку. Тогда будем смотреть.

Russk1j пишет:

Где в коментарии вы писали время, достаточное для поворота "ВРЕМЯ_ДОСТАТОЧНОЕ_ДЛЯ ПОВОРОТА"


Это тоже самое время которое вы использовали в delay().
Откуда вы эту цифру брали? И главное "зачем"?

А затем что серва не умеет "поворачиватся моментально". У нее есть какая-то конечная скорость поворота. Чем на больше угол поворачиваем - тем дольше это займет.

Если нам достаточно того что "повернулось", то собственно кроме myServ.write ничего и не нужно вообще.
Если же мы хотим что-то сделать когда серва стала в новую позицию - либо delay() либо вот тот подход что я дал выше.

К сожалению докладывать "я вышла на позицию" - серва не умеет. Поэтому приходится давать ей время на исполнение команды. Тупо скомандовали "крутись", подождали какое-то время и надеемся что она уже заняла нужную позицию.

Какое время? Ну можно час подождать. За час - точно докрутится :) Если не хочется за час - можем посмотреть в спецификацию сервы, там обычно пишут какая у нее скорость в "градусы в минуту".
Если "серва кровей неизвестных". Ну тупо говорим ей "повернись от 0 до 180" и с помощью секундомера замеряем сколько это заняло :)

Если нам "торопится некуда". То можно после любой команды ждать вот это замерянное время. Если она предположим 0 до 180 крутится 2 сек., то если мы скомандуем поворот "от 40 до 45 градусов" и подождем 2 секунды, она, к этому времени уже точно будет стоять на 45-градусах.

Если мы "торопимся" и не хотим ждать "впустую". Ну значит вычисляем сколько занимает поворот на один градус (время_полного_поворота/180). Вычисляем на сколько нам нужно повернуть серву (старая_позиция - новая_позиция).
Ну а зная "время поворота на 1 градус" и "на сколько грудусов поворачиваем" - не трудно вычислить и "сколько времени нужно ждать" (только не забываем взять модуль от вычесленного. Отрицательного времени не бывает).
Ну и можно добавить к "вычесленному" еще некоторое время "про запас". На всяк случай (ну питание там подсело и серва стала медленей крутится и т.п.)

 

leshak
Offline
Зарегистрирован: 29.09.2011
maksim
Offline
Зарегистрирован: 12.02.2012

Эта строчка millis()=servoOnTime; вряд-ли скомпилируется. millis()

leshak
Offline
Зарегистрирован: 29.09.2011

 

maksim пишет:

Эта строчка millis()=servoOnTime; вряд-ли скомпилируется. millis()

Не угадали :) Все навернется раньше.  Причем не один раз :( До этой строчки еще добраться нужно.

maksim
Offline
Зарегистрирован: 12.02.2012

Так я не гадал, это еще одна ошибка, на которую стоит обратить внимание. Ну а что раньше или позже это не важно, результат один - если не исправить в том числе эту строку компиляции не будет.

Russk1j
Offline
Зарегистрирован: 03.05.2012

 Спасибо за развернутые ответы), буду искать

leshak
Offline
Зарегистрирован: 29.09.2011

Russk1j пишет:

 Спасибо за развернутые ответы), буду искать

Что вы искать собрались-то? Нуежели я всех так запугал посылками в гугл ? :)

Искать ничег не нужно. Компилятор же вам сам говорит

И что ему не нравится (в оранжевой строке)  и где (подсвечивает строку). Осталось только взять словарик и перевести. Попытатся понять и исправить. Компилируем. Если угадали "что оно хотело" - "споткнется" на следующей ошибке. С ней - опять тоже самое. Если не выходит - сообщить тут. "Вот оно мне выдает такую ошибку", а не абстрактное "ой, не работает".

В разделе "дополнительная инфа" - самая важная - первая ошибка. На остальные часто можно не обращать внимания, так как они часто является "эхом" первой ошибки.

Russk1j
Offline
Зарегистрирован: 03.05.2012

 ну да, глупая ошибка)
А еще не поскажете,возможно ли реализовать с помощью одного УЗ датчика объезд предмета, и чтоб он восстановил свою траекторию движения. Вот он ехал прямо, встретил препятствие, обвернул его и дальше прямо поехал? Можно конечно просто задать так чтобы он при появлении значения с датчика меньше 20 делал полуокружность там с каким-нибудь радиусом, но а если стена будет, то уже не очень хорошее решение. Я как раз для этого и спрашивал можно ли так :

"Робот едет, датчик снимает показания расстояния, серва вращает датчик на угол градусов 60 туда/обратно, не много, чтобы только видеть перед собой что находится. Все нормально препятствия нет.
Как только что-то появляется, т.е. в какой-то момент времени серва находится например в левом положении при каком-то угле и значение датчика показывает меньше 20, т.е. нужно поворачивать, и тут как раз в зависимости куда смотрит серва, в противоположную сторону подвернуть роботу чтобы не врезаться. Как то так"

leshak
Offline
Зарегистрирован: 29.09.2011

Russk1j пишет:

 ну да, глупая ошибка)

Почему глупая? Обычная. Такую ошибку любой программист 5-ть раз в час делает. Просто "правит" ее, благодаря опыту, за 2 сек.

Russk1j пишет:

А еще не поскажете,возможно ли реализовать с помощью одного УЗ датчика объезд предмета, и чтоб он восстановил свою траекторию движения. 

Теретически - можно.  Практически - очень сложно. Банально потому что трудно повернуть, к примеру "ровно на 90%", трудно проехать скажем "ровно 20 см" (или узнать сколько мы проехали). На "идеальной подвеске", идеально ровном полу, с идеальными моторами - без проблем. С реальными - не реально :)

Но, прежде чем дальше ехать/менять тему. Вы со следующими ошибками разберитесь. Это же была только "первая в ряду". И синтаксических там еще пара, и логические есть. Или уже "все поправили, все заработало, переходим к следующей задаче"?

Russk1j
Offline
Зарегистрирован: 03.05.2012

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

наверно все-таки не нужно было цикл for ставить, вы писали там if
 

#include <Servo.h>
Servo myServo;
int servoPin = 9;
void setup()
{
  myServo.attach(servoPin);  
}
unsigned long servoOnTime=0;

void loop()
{
  for (int i=40; i<=120; i=i+10)
  {
     myServo.write(i); // командуем занять новую позицию
     servoOnTime=millis(); // запомнили когда дали команду серве
     
  };
  
  if(servoOnTime &&   ( (millis()-servoOnTime)>2000) // и прошло достаточно времени
     )
    {
       servoOnTime=millis();
       servoOnTime=0; // выключили отсчет времени поворота, что-бы "КОД который нужно" выполнился только один раз
    }
  
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

>наверно все-таки не нужно было цикл for ставить, вы писали там if

 

Верно. Что у вас вышло? Попробуйте в голове выполнить все что вы скомандовли ардуине.

Вначали вы ее сказали стань в 40 (запомнили время), потом, сразу, сказали стань в 50 (запомнили время), потом в 60ть....
вообщем "пробежались по всему ряду" без каких либо пауз.
И только ПОСЛЕ ВСЕГО этого решили подождать две секунды и сделали "непонятно что" хоть и синтаксически верно.

В чем смысл строки 22 если в 23 вы обнуляете переменную? Вообщем "плохо от этого не будет", но и пользы - никакой.
В 22 два вы должны делать полезное. То что нужно было сделать через две секунды после начала выполненения сервой команды.

Например сделать замер замер своего сенсора или выдать на серву новую команду-угол (намек!).
Вместо замера сенсора, пока, можно "мигнул диодом" ("условно измерил").

Вообщем попробуйте пройти по каждой строчке и понято "что она делает". Ответить на вопрос "зачем она". Не нужно брать мой код как "магию которая работает" (или нет :)
Нужно "понять идею" и уж "подгонять к своей задаче".

Вот смотрите. Раз вы решили стартовать серву сразу от включения микроконтроллера, а не по какому-то условию (нажатие кнопки или еще что).
То... может первую(!) команду на поворот сервы (и запоминание когда) стоит выдавать в setup а не loop()?
Да и раз раз вы хотите "начинать крутить как только так сразу", то ведь и условие не нужно? Логично?

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

Напомню, на всяк случай, что setup() - эта функция которая вызывается один раз при запуске. А loop() - "крутится бесконечно"
То есть как только функция loop() доходит до конца - опять начинается ее выполнение с начала.

 

Russk1j
Offline
Зарегистрирован: 03.05.2012

 Вот при такоом решении движки дергаются, не могу понять почему, серва крутится как надо.

Может и правда в setup() сделать, но как, тем более вы сами сказали что она выполнится только один раз.

#include <Servo.h>
#include <AFMotor.h>
Servo LexaServo;
int servoPin = 9;
AF_DCMotor motor1(1); //правый
AF_DCMotor motor2(2); //Левый 
int napr=1;
const int Trig = 2; 
const int Echo = 12; 
unsigned long prevServoTime =0;
int ServoPos=0;
void setup()
{
pinMode(Trig, OUTPUT); 
pinMode(Echo, INPUT); 
LexaServo.attach(servoPin);
Serial.begin(9600); 
}

unsigned int time_us=0;
unsigned int distance_sm=0;

void loop()
{

if ((millis()-prevServoTime)>200)
{
if(ServoPos>135) {napr=-10;} //направление сервы
if(ServoPos<45) {napr=10;} //направление сервы
ServoPos=ServoPos+ napr;//меняем положение сервы
LexaServo.write(ServoPos); // говорим серве куда идти
digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
digitalWrite(Trig, LOW); // Затем убираем 
time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
distance_sm=time_us/58; // Пересчитываем в сантиметры
Serial.println(distance_sm); // Выводим на порт
prevServoTime=millis();
}
if (distance_sm<20) // Если расстояние менее 20 сантиметром 
{ 
motor1.run(FORWARD);
motor2.run(BACKWARD); //BACKWARD

motor1.setSpeed(254);
motor2.setSpeed(254);
} 
else 
{ 
motor1.run(FORWARD);
motor2.run(FORWARD);

motor1.setSpeed(254);
motor2.setSpeed(254);
}
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Очень похоже на правду.
Но смотрите.
Строка 31.
Вы дали команду серве "крутись".
И сразу, без паузы, в строке 32 начали работать с датчиком растояния.
Но ведь серва в этот моменту крутится. Мы же не выждали время.
Вы померяли растояние, а потом "ждете".

Мне кажется логичней было-бы, внутри этого

if ((millis()-prevServoTime)>200)

Вначале провести замеры (этот if нам говорит о том, что с последнего поворота сервы прошло достаточно времени и она уже стоит в нужном положении), а уж потом "крутить серву".

Далее, 200 - не маловато? Попрбуйте, для тестовых целей сделать там что-то "явно большое". Что-бы эти остановки сервы вы видили прямо на глаз.
Когда отладите - потом уменьшите. Что-бы "не дуплил"

Next:
Вы вначале даете моторам команду на включение, а потом говорите "с какой скоростью".
Вы пробовали "сами в голове" попытатся выполнить эти команды?
Да и вообще непонятно, раз эти скорости всегда одинаковы, зачем они попали внутрь обоих вариантов if-а из строки 39?
Зачем это дублирование? Раз скорость моторов не зависит от дистанции, то может стоить вынести их за пределы if?
А если еще глубже глянуть и увидить что мы никогда не меняем эту скорость, то может ее вообще в setup() один раз установить и все?

Next. Оформление кода. Для читабильность, обычно "то что внутри фигурных скобок", пробелами или табами чуть-чуть смещают вправо. Делают отступы. Так четче видно "кто в кого вложен", где if начался, а где закончился.
Можете, в ArduinoIDE нажать Ctrl-T и она сама попытается "красиво отформатировать".

Примерно так:

#include <Servo.h>
#include <AFMotor.h>
Servo LexaServo;
int servoPin = 9;
AF_DCMotor motor1(1); //правый
AF_DCMotor motor2(2); //Левый 
int napr=1;
const int Trig = 2; 
const int Echo = 12; 
unsigned long prevServoTime =0;
int ServoPos=0;
void setup()
{
  pinMode(Trig, OUTPUT); 
  pinMode(Echo, INPUT); 
  LexaServo.attach(servoPin);
  Serial.begin(9600); 
}

unsigned int time_us=0;
unsigned int distance_sm=0;

void loop()
{

  if ((millis()-prevServoTime)>200)
  {
    if(ServoPos>135) {
      napr=-10;
    } //направление сервы
    if(ServoPos<45) {
      napr=10;
    } //направление сервы
    ServoPos=ServoPos+ napr;//меняем положение сервы
    LexaServo.write(ServoPos); // говорим серве куда идти
    digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
    digitalWrite(Trig, LOW); // Затем убираем 
    time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
    distance_sm=time_us/58; // Пересчитываем в сантиметры
    Serial.println(distance_sm); // Выводим на порт
    prevServoTime=millis();
  }
  if (distance_sm<20) // Если расстояние менее 20 сантиметром 
  { 
    motor1.run(FORWARD);
    motor2.run(BACKWARD); //BACKWARD

      motor1.setSpeed(254);
    motor2.setSpeed(254);
  } 
  else 
  { 
    motor1.run(FORWARD);
    motor2.run(FORWARD);

    motor1.setSpeed(254);
    motor2.setSpeed(254);
  }
}

 

Ведь легче же понять логику, правда?

Но лично я, предпочитаю "сам руками". Еще при написании. Tab-ами отодвигать.
А если нужно "поправить", то выделяем несколько строк. И нажимаем Tab, что бы их все сразу сместить вправо
и Shift-Tab - влево.

И еще. Вы начали хорошие начинание по поводу выводя дистанции в Serial. Для отладки.
Я бы добавил, перед строчкой 36.

Serial.print(millis(),DEC);Serial.print(" dist: ");

Тогда вы будете видить еще и время "когда сделали замер".

И при включении моторов, тоже сделал

Serial.print(millis(),DEC);Serial.print(" motors: ");
Serial.println(" F B") // и " F F" для второго случая

Тогда вы в логе будуте видиеть все что и когда происходит у вас внутри скетча. 
и самому понимать/искать логические ошибки легче. И на форуме можно не словами рассказыать-описывать, а просто дать лог. По коротому видно как оно у вас работает.

 P.S. А вообще прогресс у вас - просто замечательный. Такими темпами, через пару недель, вы уже сами сможете новичков консультировать :)

 

Russk1j
Offline
Зарегистрирован: 03.05.2012

Конечно понятнее если отступы делать) пропустил я этот момент. А код тоже помогли), сам я что-то тупил. 
Осмыслил, вроде все ясно, только вод дигатели дергаются( Может токи скачут, незнаю. Наверно шаговый двигатель задействую вместо сервы, там и задержек нету.
На счет повторов скорости да, вообще планировал движение вперед на 200, а разворот уже 254, где условие, один движок вперед, а другой назад.
Спасибо еще раз за ценные пояснения и советы), так проще разбираться

maksim
Offline
Зарегистрирован: 12.02.2012

Russk1j пишет:
 Наверно шаговый двигатель задействую вместо сервы, там и задержек нету.
Еще как есть, они есть в самой библе, наоборот при работе с сервой нет задержек, в стандартной библе для шаговиков пока крутится двигатель все остальное ждет.

leshak
Offline
Зарегистрирован: 29.09.2011

Russk1j пишет:

Конечно понятнее если отступы делать) пропустил я этот момент. А код тоже помогли), сам я что-то тупил. 
Осмыслил, вроде все ясно, только вод дигатели дергаются( Может токи скачут, незнаю. Наверно шаговый двигатель 

Попробуйте выяснить в чем именно у вас проблема. "В логике" или "в железе". Напишите отдельный скетч. Без серв, без сонаров и проч. Который только "крутит движки" и больше ничего.  Разделяй и властвуй :)

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

Вообщем выясните для начала "в какой области проблема" (железо или логика), а уж потом можно будет думать как ее устранить.

 

Russk1j
Offline
Зарегистрирован: 03.05.2012

 Ок, буду эксперементировать

Russk1j
Offline
Зарегистрирован: 03.05.2012

 Здравствуйте, вот вобщем я решил под себя доработать программу с этой темы:
http://arduino.ru/forum/proekty/arduino-robot-dlya-nachinayushchikh

Решил использовать еще одну библиотеку по причине того что я не знаю какие пины задействованы для работы через мотор шилд.
В общем двигатели рывками синхронно с сервой делают примерно четверть оборота колесами и поворачивают серву на 10 градусов. Дальнометр выдает нули.
 

#include <Servo.h> 
#include <LMotorShield.h> 
#include <AFMotor.h>

 LMotorShield lms; 
 int Trig = 12;               
 int Echo = 2;                
 int i; 
 int j; 
 int p[18]; // массив, здесь будем записывать данные с ИК дальномера    
 int gp,gp1,gp2,g; 
 int b; 
 AF_DCMotor motor1(1); //правый
 AF_DCMotor motor2(2); //Левый 
 void setup() { 
 {    
     Serial.begin(9600); 
     lms.begin(LMS_SERVOS);
     pinMode(Trig,OUTPUT);        
     pinMode(Echo,INPUT);  
 }    
 /*pinMode(3,OUTPUT); // Motor A скорость 
 pinMode(7,OUTPUT); // Motor A направление 
 pinMode(11,OUTPUT); // Motor B скорость 
 pinMode(8,OUTPUT); // Motor B направление 
 pinMode(2,OUTPUT); // Motor A стоп, пуск 
 pinMode(4,OUTPUT); // Motor B стоп, пуск */
 } 
 
unsigned int time_us=0;
unsigned int distance_sm=0;

 void loop() 
 { 
  j=0;    
 for (j=0;j<18;j++){  // для j от 0 до 18 
 lms.servoWrite(1,j*10); // вращение сервы по 10 градусов 

 digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
 //delayMicroseconds(10); // Удерживаем 10 микросекунд 
 digitalWrite(Trig, LOW); // Затем убираем 
 time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
 gp=time_us/58; // Пересчитываем в сантиметры
 delay(50); 
 p[j]=gp; // записываем это значение в массив 
 Serial.println(p[j]); // выводим на экран 

   if (p[j]<15)
   {     
      motor1.run(FORWARD);
      motor2.run(FORWARD); //BACKWARD
      motor1.setSpeed(254);
      motor2.setSpeed(254);
      delay (50);
      motor1.run(RELEASE);
      motor2.run(RELEASE); 
      delay(100); 
    }
 else {              // Иначе 

     lms.servoWrite(1,90); // поворачиваем голову вперед 
     delay(200); 
     digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
     //delayMicroseconds(10); // Удерживаем 10 микросекунд 
     digitalWrite(Trig, LOW); // Затем убираем        
     time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
     gp=time_us/58; // Пересчитываем в сантиметры
     Serial.println(gp); // Выводим на порт 
     while(gp<15){       // поворачиваемся, пока не заметим предмет    
     //motorRun();
     motor1.run(FORWARD);
     motor2.run(FORWARD); //BACKWARD
     motor1.setSpeed(254);
     motor2.setSpeed(254);
     if (j>9){            // если предмет с лева, то 
     //Spin_Left();// поворот в сторону объекта 
     motor1.run(BACKWARD);
     motor2.run(FORWARD); //BACKWARD
     motor1.setSpeed(254);
     motor2.setSpeed(254);
     } 
     else {              // иначе поворот вправо 
     //Spin_Right(); 
     motor1.run(FORWARD);
     motor2.run(BACKWARD); //BACKWARD

     motor1.setSpeed(254);
     motor2.setSpeed(254);
     } 
     delay (10);
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
      //delayMicroseconds(10); // Удерживаем 10 микросекунд 
      digitalWrite(Trig, LOW); // Затем убираем 
      time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
      gp=time_us/58; // Пересчитываем в сантиметры 
      Serial.println(gp); // Выводим на порт
      delay(50);     
     } 
    digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
    //delayMicroseconds(10); // Удерживаем 10 микросекунд 
    digitalWrite(Trig, LOW); // Затем убираем   
    time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
    gp=time_us/58; // Пересчитываем в сантиметры
    Serial.println(gp); // Выводим на порт
    delay(50); 
    while(gp<10){    //Двигаемся вперед пока предмет не будет на расстоянии 10 см. 
    motor1.run(FORWARD);
    motor2.run(FORWARD); //BACKWARD
    motor1.setSpeed(254);
    motor2.setSpeed(254);
    delay (50); // время движения 
    
    digitalWrite(Trig, HIGH); // Подаем сигнал на выход микроконтроллера 
    //delayMicroseconds(10); // Удерживаем 10 микросекунд 
    digitalWrite(Trig, LOW); // Затем убираем 
    time_us=pulseIn(Echo, HIGH); // Замеряем длину импульса 
    gp=time_us/58; // Пересчитываем в сантиметры
    Serial.println(gp); // Выводим на порт
    delay(50); 
   } 
   lms.servoWrite(1,0); // убираем голову в сторону, чтобы она не мешала захвату предмета и транспортировке 
   delay(100); 
   motor1.run(FORWARD);
   motor2.run(FORWARD); //BACKWARD
   motor1.setSpeed(254);
   motor2.setSpeed(254);
   delay (700); // время движения
   motor1.run(RELEASE);
   motor2.run(RELEASE);
   delay(500); 
      
     motor1.run(BACKWARD);
     motor2.run(BACKWARD); //BACKWARD
     motor1.setSpeed(254);
     motor2.setSpeed(254);
     delay(100); 
     motor1.run(BACKWARD);
     motor2.run(FORWARD); //BACKWARD
     motor1.setSpeed(254);
     motor2.setSpeed(254);
     delay(600); 
   } 
   } 
   }

Что не так подскажите пожалуйста