Автономный робот обнаруживает линию и следует ей

Создаем на основе Ардуино автономного робота, который способен обнаруживать черную линию и может следовать по ней. Также этот робот может нести полезную нагрузку 200-300 грамм. Этот проект для нас является продолжением темы создания полезных проектов. Первым таким проектом стали Очки для слабовидящих. Этот проект также может быть полезен слабовидящим, т.к. он может стать помощником в перемещении слепых людей по квартире или по дому.

Шаг 1. Комплектующие

Комплектующие, используемые в этом проекте мы перечислим ниже. Скажем так, это даже не робот, а, практически, судно на воздушной подушке.

Компоненты оборудования

  • Arduino Uno × 1
  • Датчик QTR × 7
  • Набор опор DGI × 4
  • 11,1 В 2200 мАч LiPo аккумулятор × 1
  • Плата распределения питания × 1
  • Антистатическая пена, высокая плотность × 1

Программное обеспечение

Ручные инструменты

Шаг 2. Проект

Задача была спроектировать и построить судно на воздушной подушке, способное поднимать груз весом 200-300 грамм и самостоятельно следовать курсу. Бюджет составлял около 200 долларов, что оказалось достаточно для такого проекта. Управление тягой и мощностью осуществляется частями дронов в полустандартной конфигурации, а плата распределения мощности (PDB, Power Distribution Board) подает питание на 4 двигателя, управляющих нашим "судном".

Каждый двигатель подключен к электронному контроллеру скорости (ESC, Electronic Speed Controller), который позволяет индивидуально контролировать скорость каждого двигателя. Эти ESC подключены к Arduino Uno с шилдом Protoboard, который позволяет управлять каждым двигателем с помощью кода. Линия следования "судна" обрабатываются набором датчиков отражения QTR в передней части корабля.

Через библиотеку QTR Arduino они используются для оценки того, что вдоль набора центрирована линия. Датчики QTR необходимо калибровать каждый раз при включении, что позволит работать проекту в новых условиях.

Набор датчиков QTR в передней части корабля, который обнаруживает линию

Arduino принимает данные датчика QTR и оценивает положение линии. Затем он сигнализирует двум задним вентиляторам о корректировке курса. Судно двигается вперед, если линия обнаружена вблизи центра "судна".

Шаг 3. Схема соединений

Все комплектующие нашего судна соединяем согласно схеме выше. Вы можете увеличить схему, кликнув на неё.

Шаг 4. Код

Скачать архив с кодом или скопировать сам код нашего судна Ардуино на воздушной подушке вы можете ниже.

/*Code Author: Miles Nash May, 2019
 * Github: https://github.com/miles-nash/Hovercraft
 * Line Following Hovercraft project
 * 1st place hovercraft final for the Lockheed Martin Explorer Post
 * Teamates Cooper Kern, Dylan Bolt, and Oliver Testerman
 * Team: There is no sound in space
*/
#include <QTRSensors.h>
#include <Servo.h>

QTRSensors qtr;
const uint8_t SensorCount = 7;
uint16_t sensorValues[SensorCount];

Servo liftL;
Servo liftR;
Servo steeringL;
Servo steeringR;

static int SPEED = 40; // speed of travel out of 180

void setup() {
  // setup each motor, (pin, min pwm, max pwm)
  liftL.attach(5,1000,2000);
  liftR.attach(6, 1000, 2000);
  steeringL.attach(10, 1000,2000);
  steeringR.attach(9, 1000, 2000);
  
  calibrateESC();
  
  delay(1000);
  startHover();
  delay(1000);
  setupQTR();
}

void loop() {

  //adjust these to calibrate the hovercraft
  startHover();
  int tolerance = 1000;
  int timeOn = 500;
  int timeOff = 500;
  int power = 90;
  int forwardPower = 160;

  
  uint16_t position = qtr.readLineBlack(sensorValues);

  if(position > 3000 + tolerance){
    steeringL.write(power);
    delay(timeOn);
    steeringL.write(0);
    digitalWrite(13,HIGH);
    delay(timeOff);
    digitalWrite(13,LOW);
  }else if(position < 3000 - tolerance){
    steeringR.write(power + 50); //changed to correct for drift due to weight distribution
    delay(timeOn);
    steeringR.write(0);
    digitalWrite(13,HIGH);
    delay(timeOff);
    digitalWrite(13,LOW);
  }
  else{
    steeringL.write(forwardPower);
    delay(timeOn);
    steeringL.write(0);
    delay(100);
    steeringR.write(forwardPower);
    delay(timeOn);
    steeringR.write(0);
    delay(100);
  }

}

void startHover() {
  //power up the downward facing motors to hover the craft
  liftL.write(110); //100 is least feasable hover speed
  liftR.write(110);
}


void calibrateESC(){
  // callibrate the escs
  //escs can have differing min and max pwm values, we set these here
  liftL.write(180);//set max esc value
  liftR.write(180);
  steeringL.write(180);
  steeringR.write(180);
  delay(5000);
  liftL.write(0);//set min esc value
  liftR.write(0);
  steeringL.write(0);
  steeringR.write(0);
  delay(5000);
}

//calibrates and sets up the line following sensor. Glide the sensor array across the line a few times while the LED is on
void setupQTR(){
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){2,3,4,14,15,12,17}, SensorCount);
  qtr.setEmitterPin(11);

  delay(500);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // turn on Arduino's LED to indicate we are in calibration mode

  // 2.5 ms RC read timeout (default) * 10 reads per calibrate() call
  // = ~25 ms per calibrate() call.
  // Call calibrate() 200 times to make calibration take about 10 seconds.
  for (uint16_t i = 0; i < 100; i++)
  {
    qtr.calibrate();
  }
  digitalWrite(LED_BUILTIN, LOW); // turn off Arduino's LED to indicate we are through with calibration

  // print the calibration minimum values measured when emitters were on
  Serial.begin(9600);
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(qtr.calibrationOn.minimum[i]);
    Serial.print(' ');
  }
  Serial.println();

  // print the calibration maximum values measured when emitters were on
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(qtr.calibrationOn.maximum[i]);
    Serial.print(' ');
  }
  Serial.println();
  Serial.println();
  delay(1000);
}

Шаг 5. Тестирование

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

Шаг 6. Итог

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

Ардуино+