Нужна помощь с програмой для робота...

Тема в разделе "Моторы, сервоприводы, робототехника", создана пользователем Nitro77rus, 14 дек 2014.

  1. Nitro77rus

    Nitro77rus Гик

    Собрал робота из Arduino UNO + Arduino Motor Shield + серва и ИК-датчиком, пару дней ковыряний и конструкция начала работать :) Но один момент ни как не могу решить :( Прошу помощи. Это чудо ездит и даже объезжает препятствия. Но вот когда заезжает в узкое место, то крутиться пока не развернётся. Хотелось, что бы он, уперевшись в препятствие, по алгоритму проверил расстояние по бокам и если он маленькое, выехал задним ходом и нашёл другой маршрут.

    Код ( (Unknown Language)):


    //==================================================================================
    //Прога для робота на гусеницах
    //==================================================================================
    #include <Servo.h>
    //Контакты Motor Shield (DIR_A 12, DIR_B 13, PWM_A 3, PWM_B 11, BRAKE_A 9, BRAKE_B 8)
    #define SPEED_LEFT  11
    #define SPEED_RIGHT  3
    #define DIR_LEFT  13
    #define DIR_RIGHT  12
    #define BRAKE_LEFT  8
    #define BRAKE_RIGHT  9
    // Датчик
    #define IR_RADAR  A2
    // Расстояние в см
    float dist(){
      float volts = analogRead(IR_RADAR)*0.0048828125;
      float distance = 65*pow(volts, -1.10);
      return distance;
    }
    //Препятствие
    const int dangerThresh = 50;
    int dist_l, dist_r;
    // Серво
    #include <Servo.h>
    #define SERVO  2
    Servo radarServo;
    //==================================================================================
    //Маршрут движения
    void CalcMove()
    {
     if (dist_l>dist_r) //если слево меньше...
     //...то едем вправо
     {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, HIGH);
      digitalWrite(DIR_RIGHT, LOW);
      delay(700); //время на манёвр
     }
     else if (dist_r>dist_l) //если справо меньше...
     //...едем влево
     {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, LOW);
      digitalWrite(DIR_RIGHT, HIGH);
      delay(700); //время на манёвр
     }
     else if (dist_l, dist_r > dangerThresh*2)
     {
     analogWrite(SPEED_LEFT, 75);
     analogWrite(SPEED_RIGHT, 75);
     digitalWrite(DIR_LEFT, LOW);
     digitalWrite(DIR_RIGHT, LOW);
     delay(1000);
     }
    }
    //==============================================================================
    void setup()
    {
      // Выходы двигателей  
      pinMode(SPEED_LEFT, OUTPUT);
      pinMode(SPEED_RIGHT, OUTPUT);
      pinMode(DIR_LEFT, OUTPUT);
      pinMode(DIR_RIGHT, OUTPUT);
      // Подключение к серво  
      radarServo.attach(SERVO);
      // Выставить серво по центру (обычно 90)
      radarServo.write(86);
      // Настраиваем порт для мониторинга данных  
      Serial.begin(9600);  
      // Пауза перед началом работы
      delay(4000);
    }

    //==============================================================================
    void loop()
    {
      //Вывод данных с датчика в см
      Serial.println(dist());
      //Расчет маршрута объезда препятствия
      int dist_f = dist(); //расстояние спереди
      if (dist_f>dangerThresh) //...если больше заданного вначале
      //едем вперёд
      {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, LOW);
      digitalWrite(DIR_RIGHT, LOW);
      }
      else //...иначе
      {
      analogWrite(SPEED_LEFT, 0);
      analogWrite(SPEED_RIGHT, 0); //Остановка!
      radarServo.write(10); //Поварачиваем датчик вправо
      delay(500); //время на поворот сервы
      dist_r = dist(); //расстояние справо
      delay(500); //врямя для измерения
      radarServo.write(160);//поворот датчика влево
      delay(700); //время для поворота сервы
      dist_l = dist(); //растояние слево
      delay(500); //замеряем
      radarServo.write(86); //датчик в центр
      delay(100); //небольшая выдержка
      CalcMove(); //получив данные идём расчитывать маршрут объезда ;)
      }

      }

     
    Проблема в блоке расчёта маршрута, ели я правильно понимаю...
     
  2. Mozg00FF

    Mozg00FF Нерд

    Первое что бросается в глаза - строчка:
    Код (Text):
    else if (dist_l, dist_r > dangerThresh*2)
    эта запись эквивалентна записи:
    Код (Text):
    else if (dist_r > dangerThresh*2)
    а то, что вы видимо хотели написать пишется так:
    Код (Text):
    else if (dist_l > dangerThresh*2 && dist_r > dangerThresh*2)
    (это так, не вникая в суть кода)
     
    Nitro77rus нравится это.
  3. Mozg00FF

    Mozg00FF Нерд

    А в остальном, если так прикинуть - то расстояния по бокам практически никогда не будут одинаковыми, т.е. этот кейс никогда не сработает, поэтому (если я правильно понял и код последнего ифа двигает назад) я написал бы так:
    Код (Text):
    //Маршрут движения
    void CalcMove()
    {
        // если по бокам мало места - едем назад
      if (dist_l < dangerThresh*2 && dist_r < dangerThresh*2)
      {
        analogWrite(SPEED_LEFT, 75);
        analogWrite(SPEED_RIGHT, 75);
        digitalWrite(DIR_LEFT, LOW);
        digitalWrite(DIR_RIGHT, LOW);
        delay(1000);
      }
      else if (dist_l>dist_r) //если слева меньше...
    //...то едем вправо
    {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, HIGH);
      digitalWrite(DIR_RIGHT, LOW);
      delay(700); //время на манёвр
    }
    else if (dist_r>dist_l) //если справа меньше...
    //...едем влево
    {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, LOW);
      digitalWrite(DIR_RIGHT, HIGH);
      delay(700); //время на манёвр
    }
    }
     
    код поворотов влево и вправо не менял, т.к. сам код не соответствует тому что написано в комментариях, но если работает, то ок))
     
    Nitro77rus нравится это.
  4. Nitro77rus

    Nitro77rus Гик

    Вы говорите о том, что лево и право перепутаны? Это я в процессе постройки робота перевернул серву :)
    Или ещё где накосячил?

    За подсказку ОГРОМНОЕ спасибо! :)

    Теперь едет назад при заданных условиях. :)

    И дописал кусочек, что бы обратно в тупик не заезжал ;)

    Код ( (Unknown Language)):

    //Маршрут движения
    void CalcMove()
    {
      // если по бокам мало места - едем назад
      if (dist_l < dangerThresh*2 && dist_r < dangerThresh*2)
      {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, HIGH);
      digitalWrite(DIR_RIGHT, HIGH);
      delay(2000);
      Tupik(); //идем расчитывать маршрут объезда тупика
      }
      else if (dist_l>dist_r) //если слева меньше...
      //...то едем вправо
      {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, HIGH);
      digitalWrite(DIR_RIGHT, LOW);
      delay(700); //время на манёвр
      }
      else if (dist_r>dist_l) //если справа меньше...
      //...едем влево
      {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, LOW);
      digitalWrite(DIR_RIGHT, HIGH);
      delay(700); //время на манёвр
      }
    }
    //==================================================================================
    //Маршрут объезда тупика
    void Tupik()
    {
      //Расчет маршрута выезда из тупика
      int dist_f = dist(); //расстояние спереди
      if (dist_f>dangerThresh) //...если больше заданного вначале
      //едем вперёд
      {
      analogWrite(SPEED_LEFT, 75);
      analogWrite(SPEED_RIGHT, 75);
      digitalWrite(DIR_LEFT, LOW);
      digitalWrite(DIR_RIGHT, LOW);
      }
      else //...иначе
      {
      //Остановка!
      analogWrite(SPEED_LEFT, 0);
      analogWrite(SPEED_RIGHT, 0);
      radarServo.write(10); //Поварачиваем датчик вправо
      delay(500); //время на поворот сервы
      dist_r = dist(); //расстояние справо
      delay(500); //врямя для измерения
      radarServo.write(160); //поворот датчика влево
      delay(700); //время для поворота сервы
      dist_l = dist(); //растояние слево
      delay(500); //замеряем
      radarServo.write(86); //датчик в центр
      delay(100); //небольшая выдержка
      CalcMove(); //получив данные идём расчитывать маршрут объезда ;)
      }
    }
     
     
  5. Mozg00FF

    Mozg00FF Нерд

    Если судить по условию, то получается в первом случае:
    else if (dist_l>dist_r) // расстояние слева больше расстояния справа, т.е. мы должны ехать туда где больше места, т.е. влево, в комменте написано, что едем вправо
    Но если у вас он при этом едет в правильном направлении - значит после того как вы перевернули серву у вас поменялись значения переменных dist_l и dist_r, в итоге код стал правильным (но при этом как бы dist_l - уже обозначает расстояние справа а не слева).
     
    Последнее редактирование: 15 дек 2014
  6. Nitro77rus

    Nitro77rus Гик

    Ага.. так и есть, серву перевернул, поправил код, но не как правильно, а как было легче ;) А коменты не правил вовсе... На тот момент эта была не проблема, проблема была в выезде из тупика. А ща всё ок, так что перепишу остальное, точнее приведу в порядок :)

    Ещё раз спасибо за подсказку, очень помогло. Без Вас целый день ковырялся, не мог найти правильного решения.