Умный ездящий робот со "зрением" на Arduino

Туша:
Решил я сделать простого робота, который бы ездил и видел препятствия объезжая их. Купил готовую платформу с кареткой для батареек AA на 1,5v.
 
Мозг крутилок:
Так же прикупил самый распространенный драйвер двигателей L293D. Чтобы крутить моторы куда захочу, вперед - назад, туда - сюда. Но минус его в том, что он сильно греется и отрыгивает в виде тепла 1,5V, хоть и защищен от перегрева.
ENABLE 1, 2, 3, 4  - Подключается к PWM (ШИМ) входу, можно и к обычному цифровому, но ток у вас будет всегда на максимуме, а на ШИМ'е вы можете регулировать его силу. От этого мотор можно крутить медленно или быстро, как хотите в общем.
INPUT 1, 2, 3, 4 - к любым цифровым входам
OUTPUT 1, 2, 3, 4 - подключают + и - моторов 
VCC1 - питание логики чипа +5V
VCC2 - питание моторов +5V - 36V
GND - к земле
Зенки:
В виде зрения я буду использовать ультразвуковой дальномер HC-SR04 (самый распространенный, стоит ~200р)
 
Особенности
Напряжение питания: 5V DC
Ток покоя: <2mA
Эффективный угол: <15°
Диапазон измерения расстояния: 2–400 cm
Разрешение: 0.3 cm
VCC - к +5V
TRIG - к любому цифровому входу
ECHO - к любому PWM входу
GND - земля
Кишки:
Вот макетная плата сборки + принципиальная схема (все делается в САПР Fritzing)
 
У L293D раздельное питание самой логики и двигателей, это очень хорошо. Двигатели я запитал от 4-х батареек типа AA на 1,5v, а саму логику буду питать от кроны. Можно было бы питать и от Arduino, но там еще у нас питается ультразвуковой дальномер. Если питать Arduino, дальномер + L293D, то батарейка очень быстро сядет ну или дальномеру не будет хватать тока, поэтому я решил питать драйвер отдельной батареи крона. Саму же Arduino + дальномер от другой батареи, тоже типа крона.
Итоговый результат умной повозки:
 
Магия:
Для управления робота я написал отдельную библиотеку, дабы не загромождать и не прописывать все скетче, а вызывать все функции которые мне нужны.
EasyRo.cpp :


#include "Arduino.h"

#include "EasyRo.h"

EasyRo::EasyRo(int MOTOR_LEFT_OUT1, int MOTOR_LEFT_OUT2, int MOTOR_LEFT_PWM,

int MOTOR_RIGHT_OUT1, int MOTOR_RIGHT_OUT2, int MOTOR_RIGHT_PWM)

{

pinMode(MOTOR_LEFT_OUT1, OUTPUT);

pinMode(MOTOR_LEFT_OUT2, OUTPUT);

pinMode(MOTOR_LEFT_PWM, OUTPUT);

pinMode(MOTOR_RIGHT_OUT1, OUTPUT);

pinMode(MOTOR_RIGHT_OUT2, OUTPUT);

pinMode(MOTOR_RIGHT_PWM, OUTPUT);


PIN_MOTOR_LEFT_OUT1 = MOTOR_LEFT_OUT1;

PIN_MOTOR_LEFT_OUT2 = MOTOR_LEFT_OUT2;

PIN_MOTOR_LEFT_PWM = MOTOR_LEFT_PWM;

PIN_MOTOR_RIGHT_OUT1 = MOTOR_RIGHT_OUT1;

PIN_MOTOR_RIGHT_OUT2 = MOTOR_RIGHT_OUT2;

PIN_MOTOR_RIGHT_PWM = MOTOR_RIGHT_PWM;

}


void EasyRo::FORWARD(int SPEED)

{

digitalWrite(PIN_MOTOR_LEFT_OUT1, HIGH);

digitalWrite(PIN_MOTOR_LEFT_OUT2, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT1, HIGH);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, LOW);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_LEFT_PWM, SPEED);

analogWrite(PIN_MOTOR_RIGHT_PWM, SPEED);

}

}


void EasyRo::BACKWARD(int SPEED)

{

digitalWrite(PIN_MOTOR_LEFT_OUT1, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT2, HIGH);

digitalWrite(PIN_MOTOR_RIGHT_OUT1, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, HIGH);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_LEFT_PWM, SPEED);

analogWrite(PIN_MOTOR_RIGHT_PWM, SPEED);

}

}


void EasyRo::FORWARD_LEFT(int SPEED)

{

digitalWrite(PIN_MOTOR_RIGHT_OUT1, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT1, HIGH);

digitalWrite(PIN_MOTOR_LEFT_OUT2, LOW);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_LEFT_PWM, SPEED);

}

}


void EasyRo::BACKWARD_LEFT(int SPEED)

{

digitalWrite(PIN_MOTOR_RIGHT_OUT1, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT1, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT2, HIGH);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_LEFT_PWM, SPEED);

}

}


void EasyRo::FORWARD_RIGHT(int SPEED)

{

digitalWrite(PIN_MOTOR_LEFT_OUT1, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT2, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT1, HIGH);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, LOW);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_RIGHT_PWM, SPEED);

}

}


void EasyRo::BACKWARD_RIGHT(int SPEED)

{

digitalWrite(PIN_MOTOR_LEFT_OUT1, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT2, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT1, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, HIGH);

for(int i = 0; i < SPEED; i++)

{

analogWrite(PIN_MOTOR_RIGHT_PWM, SPEED);

}

}


void EasyRo::STOP(int SPEED)

{

for(int i = SPEED; i >=5 ; i++)

{

analogWrite(PIN_MOTOR_LEFT_PWM, SPEED);

analogWrite(PIN_MOTOR_RIGHT_PWM, SPEED);

}

digitalWrite(PIN_MOTOR_LEFT_OUT1, LOW);

digitalWrite(PIN_MOTOR_LEFT_OUT2, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT1, LOW);

digitalWrite(PIN_MOTOR_RIGHT_OUT2, LOW);

}

EasyRo.h :
#include "Arduino.h"
class EasyRo
{
public:
EasyRo(int MOTOR_LEFT_OUT1, int MOTOR_LEFT_OUT2, int MOTOR_LEFT_PWM,
int MOTOR_RIGHT_OUT1, int MOTOR_RIGHT_OUT2, int MOTOR_RIGHT_PWM);
void FORWARD(int SPEED);
void BACKWARD(int SPEED);
void FORWARD_LEFT(int SPEED);
void BACKWARD_LEFT(int SPEED);
void FORWARD_RIGHT(int SPEED);
void BACKWARD_RIGHT(int SPEED);
void STOP(int SPEED);
private:
int PIN_MOTOR_LEFT_OUT1;
int PIN_MOTOR_LEFT_OUT2;
int PIN_MOTOR_LEFT_PWM;
int PIN_MOTOR_RIGHT_OUT1;
int PIN_MOTOR_RIGHT_OUT2;
int PIN_MOTOR_RIGHT_PWM;
};

Сам скетч:

#include <EasyRo.h>

#include <math.h>

#define LEFT_MOTOR_OUT_1 13

#define LEFT_MOTOR_OUT_2 12

#define LEFT_MOTOR_PWM 11

#define RIGHT_MOTOR_OUT_1 8

#define RIGHT_MOTOR_OUT_2 7

#define RIGHT_MOTOR_PWM 6

#define TRIG 4

#define ECHO 3


int time = 0;

int dist = 0;

int left = 0;

int right = 0;


EasyRo robot(LEFT_MOTOR_OUT_1,LEFT_MOTOR_OUT_2,LEFT_MOTOR_PWM,

RIGHT_MOTOR_OUT_1,RIGHT_MOTOR_OUT_2,RIGHT_MOTOR_PWM);


void setup()

{

  pinMode(TRIG, OUTPUT);

  pinMode(ECHO, INPUT);

  Serial.begin(9600);

}


void loop()

{

  robot.FORWARD(255); 

// Движемся вперед

  if(GetDist() <= 5) // Если расстояние до объекта 5 или менее сантиметров то 

  {

    robot.BACKWARD(255); // Движемся назад

    delay(1000);//Останавливаем программу на 1000 милисекунд

    robot.BACKWARD_LEFT(255); // Движемся только левым колесом назад

    delay(500);

//Останавливаем программу на 500 милисекунд

    left = GetDist(); // Получаем расстояние до ближайшего объекта в левой стороне 

    robot.FORWARD_LEFT(255); // Движемся только левым колесом вперед

    delay(1000); //Останавливаем программу на 1000 милисекунд

    right = GetDist(); // Получаем расстояние до ближайшего объекта в правой стороне 

    if(left > right) // Если в левой стороне расстояние до объекта больше то

    {

      robot.BACKWARD_LEFT(255); // Движемся только левым колесом назад

      delay(1000); //Останавливаем программу на 1000 милисекунд

      robot.FORWARD(255); // Двигаемся вперед

    }   

  }

}


int GetDist() // Получаем дистанцию до объекта в сантиметрах

{

  reget:

  digitalWrite(TRIG,HIGH);

  delayMicroseconds(10);

  digitalWrite(TRIG, LOW);

  delayMicroseconds(100);

  time = pulseIn(ECHO,HIGH);

  dist = time/58;

  if(dist < 0)

  {

    goto reget;

  }

  Serial.println(dist);

  delay(10);

  return dist;

}

Можно было бы прицепить сервопривод а на него дальномер, чтобы он мог бошкой крутить, но серва нещадно съест всю крону :(
В общем вот так :)
nektome.blog https://nektome.blog/ +7 (927) 2893774
| Комментариев: 13
    Новых комментариев: 0
  1. 0
    Ну откомпилировали программу, получили "exe". Ну и как это впилить роботу в мозг?
    Becks: Причем тут "exe"?
    Это заливается на микроконтроллер.
    #
    Написал аноним
  2. 0
    хуйня , такое 5 минут делать))
    ниже даже ссылка есть на инструкцию.
    Becks: Лооооооооооол. Я смотрю вы много сделали. Провода соединить, да, 5 минут. А программировать кто будет? Программировать нормально, 5 минут надо? Еще раз лооооол. Увы и ах, ваша "жизнь" хуйня :)
    #
    Написал аноним
  3. 0
    Спасибо! Интересный и полезный пост!
    #
    Написал Игнат Дамвротов
  4. 0
    Оно ж и хорошо! Я запостил ссылку, потому что у меня память сработала, что где-то что-то похожее видел. Первые шаги - самое приятное.
    Becks: Первые шаги - самое приятное
    ______
    В точку :) Сейчас хочу ему прикрутить серву и поставить на него дальномер, но по неосторожности угробил ее( Осталась только серва непрерывного вращения, приходится изощряться, но пока не особо выходит.
    #
    Написал onemanparty
  5. 0
    Подозрительно похоже на http://arduino.ru/forum/proekty/arduino-robot-dlya-nachinayushchikh, но вы всё равно молодец.

    Хорошо, что это кому-то интересно.
    Becks: Спасибо) Я не спорю, что похоже) Платформы они же везде продаются, да и таких роботов тысячи, но просто я сделал своего, со своей логикой)
    #
    Написал onemanparty
  6. 0
    Becks: У меня в блоге есть про детектор цвета, самый первый мой пост :)
    __
    И его уже прочел.)
    #
    Написал XRust NK
  7. +1
    Не могу плюсовать блогзаписи. Поэтому напишу тут. Очень интересно. Надеюсь что еще что-то подобное будет.
    Becks: У меня в блоге есть про детектор цвета, самый первый мой пост :)
    #
    Написал XRust NK
  8. 0
    Код лучше выкладывать на GitHub или http://pastebin.com/, тут он не читается.
    Becks: Зачем на репу выкладывать, я его так чисто для своего удобства делал.
    Ну а тут да, он плохо читается)
    #
    Написал akvntrk
  9. 0
    А глазки какие)
    Вы молодец)
    Becks: http://adoptingjames.files.wordpress.com/2012/05/wall-e1.jpg :)
    #
    Написала МурМяу
  10. 0
    такое здесь наверняка впервые)
    классно сделано)
    молодец)
    Becks: Спасибо :)
    #
    Написал аноним
  11. 0
    Самоспокойствие, просто пост неформатный для этого сайта, узковат, скажем. Отсюда и необычность.
    #
    Написала ExtraVirgin
  12. +1
    Пожалуй, самый необычный пост месяца на всём проекте. Запишите видео с работой этого детища и добавьте к посту. Интересно же и в динамике увидеть.
    Becks: Как время будет, сниму его в динамике :)
    #
    Написал Самоспокойствие
  13. +1
    Круто! Молодец!
    Becks: Благодарю)
    #
    Написал(а) Dima
  1. nektome.blog
  2. Becks Harrington
  3. Блог
  4. Умный ездящий робот со "зрением" на Arduino
Умный ездящий робот со "зрением" на Arduino