Начитавшись в интернете и в том числе на хабре о создании разнообразных роботов, я решил сделать своего. Тем более, что у меня давно без дела валяется arduino.
За неименеем денег на шасси для робота, решил сделать самое дешевое и простое. В качестве органов чувств был выбран ультразвуковой дальномер.
Мне хотелось собрать дешевую и простую в изготовлении платформу для моей ардуины.
Я попытался использовать свой радиоуправляемый джип, но мощности motorshield'а не хватало для нормального движения(я даже случайно спалил драйвер двигателя).Был необходим h-мост, состоящий из 4х транзисторов. Разбираться в схеме игрушки было лень(да и ломать не хотелось), а для пайки своего надо было рыться в закромах родины и искать транзисторы.
В моем распоряжении было несколько моторчиков, обрезки алюминевых листов и советский металлический конструктор.
Путешествуя по интернету я часто натыкался на beam-роботов, которые не имели ни колес, ни гусениц, а главное не имели редукторов.
Весь секрет состоял в моторах, которые были расположены под углом к полу. Робот стоял прямо на валах.
Это позволяет не заботиться о передаточных числах, мощностях моторов. Сами двигатели являются редукторами за счет малого диаметра вала.
Из алюминевого листа вырезал держатель моторов, прикрепил его к раме из конструктора и привинтил держатель arduino. Вроде ничего сложного, дремель, отвертка и максимум 15 минут времени.
Как упомянул выше, arduino управляет моторами через motorshield, питание у них раздельное, чтобы не спалить микропроцессор. Позже я добавил кнопку выключения. К платам подключен ультразвуковой дальномер SRF05. Он умеет работать в 2х режимах, подробно останавливаться не буду, скажу лишь, что в 1ом режиме необходимо задействовать 2 контакта(один тригер на посылку звука, второй прием данных), а 2ой соответственно 1, за что и был выбран. Для сенсора был спаян переходник, включающий сенсор во второй режим(заземляет один контакт).
На видео ниже будет показан простейший алгоритм-увидел стенку, поверни. Здесь же я приведу более содержательный код. В комментариях есть пояснения.
Алгоритм следующий:
1) повращаться вокруг своей оси и найти максимальную дистанцию
2) повернуться по направлению к максимальной дистанции
3.1) если смогли повернуться едем прямо до некоторого момента
3.2) если не смогли едем вперед
4.1) если застряли(едем вперед, а расстояние не меняется) отъезжаем назад и возращаемся к пункту 1
4.2) если доехали до стенки, останавливаемся и возвращаемся к пункту 1
Исходник:
За один вечер реально построить простейшего робота. Конечно же есть недоделки, например сенсор стоит повесить на сервомотор и провода следует привести в нормальный вид. Надеюсь вам понравится такой робот.
За неименеем денег на шасси для робота, решил сделать самое дешевое и простое. В качестве органов чувств был выбран ультразвуковой дальномер.
Задумка
Мне хотелось собрать дешевую и простую в изготовлении платформу для моей ардуины.
Я попытался использовать свой радиоуправляемый джип, но мощности motorshield'а не хватало для нормального движения(я даже случайно спалил драйвер двигателя).Был необходим h-мост, состоящий из 4х транзисторов. Разбираться в схеме игрушки было лень(да и ломать не хотелось), а для пайки своего надо было рыться в закромах родины и искать транзисторы.
В моем распоряжении было несколько моторчиков, обрезки алюминевых листов и советский металлический конструктор.
Проектирование
Путешествуя по интернету я часто натыкался на beam-роботов, которые не имели ни колес, ни гусениц, а главное не имели редукторов.
Весь секрет состоял в моторах, которые были расположены под углом к полу. Робот стоял прямо на валах.
Это позволяет не заботиться о передаточных числах, мощностях моторов. Сами двигатели являются редукторами за счет малого диаметра вала.
Постройка
Рама
Из алюминевого листа вырезал держатель моторов, прикрепил его к раме из конструктора и привинтил держатель arduino. Вроде ничего сложного, дремель, отвертка и максимум 15 минут времени.
Электроника
Как упомянул выше, arduino управляет моторами через motorshield, питание у них раздельное, чтобы не спалить микропроцессор. Позже я добавил кнопку выключения. К платам подключен ультразвуковой дальномер SRF05. Он умеет работать в 2х режимах, подробно останавливаться не буду, скажу лишь, что в 1ом режиме необходимо задействовать 2 контакта(один тригер на посылку звука, второй прием данных), а 2ой соответственно 1, за что и был выбран. Для сенсора был спаян переходник, включающий сенсор во второй режим(заземляет один контакт).
Программирование
На видео ниже будет показан простейший алгоритм-увидел стенку, поверни. Здесь же я приведу более содержательный код. В комментариях есть пояснения.
Алгоритм следующий:
1) повращаться вокруг своей оси и найти максимальную дистанцию
2) повернуться по направлению к максимальной дистанции
3.1) если смогли повернуться едем прямо до некоторого момента
3.2) если не смогли едем вперед
4.1) если застряли(едем вперед, а расстояние не меняется) отъезжаем назад и возращаемся к пункту 1
4.2) если доехали до стенки, останавливаемся и возвращаемся к пункту 1
Исходник:
#include <AFMotor.h>
#define MaxRange 23 // Как близко подъезжать к препятствиям
#define MaxTries 3 // Сколько раз пытаться найти максимум
int srfPin = 16; // Pin for SRF05
int ledPin = 2; //
AF_DCMotor motorL(2);
AF_DCMotor motorR(1);
boolean isInRange(int value,int leftBorder,int rightBorder){
return (value>leftBorder && value<rightBorder);
}
//Забрать показания сенсора
int getDistance(){
delay(50);
int duration=0; //сюда кладем время ответа
pinMode(srfPin, OUTPUT);
digitalWrite(srfPin, LOW); // заземляем контакт, перед посылкой
delayMicroseconds(2);
digitalWrite(srfPin, HIGH); // Посылаем 10микросекундный сигнал начала измерений
delayMicroseconds(10);
digitalWrite(srfPin, LOW); // Опять заземляем перед приемом ответа
pinMode(srfPin, INPUT);
duration = pulseIn(srfPin, HIGH); // Считаем время ответного сигнала
return duration/58; //возвращаем дистанцию в сантиметрах
}
//Функции движения
void goForward(){
motorL.setSpeed(255);
motorR.setSpeed(255);
motorL.run(FORWARD);
motorR.run(FORWARD);
}
void goBackward(){
motorL.setSpeed(255);
motorR.setSpeed(255);
motorL.run(BACKWARD);
motorR.run(BACKWARD);
}
void turnLeft(){
motorL.setSpeed(255);
motorR.setSpeed(255);
motorL.run(BACKWARD);
motorR.run(FORWARD);
}
void turnRight(){
motorL.setSpeed(255);
motorR.setSpeed(255);
motorL.run(FORWARD);
motorR.run(BACKWARD);
}
void stopMovement(){
motorL.run(RELEASE);
motorR.run(RELEASE);
}
// функция поиска максимума вокруг
int getMaxDistanseAround(){
unsigned long timeStart=millis();
int maxFound=0;
// выбор направления поворота случаен
if(random(100)<50){turnLeft();}else{turnRight();}
// крутимся некоторое время и ищем максимум
while(millis()-timeStart<3000){
int curDistance=getDistance();
if( curDistance > maxFound ){
maxFound=curDistance;
}
}
return maxFound;
}
// функция возвращения на максимум
boolean turnToDistance(int distance){
unsigned long timeStart=millis();
// опять случайное направление
if(random(100)<50){turnLeft();}else{turnRight();}
// крутимся некоторое время
while(millis()-timeStart<3000){
// учитывая погрешность сравниваем текущее растояние перед роботом
// и то, на которое надо выровняться
if( isInRange(getDistance(),distance-5,distance+5)){
// Пишем в usb сообщение об удаче
Serial.print("Turned to ");
Serial.println(getDistance());
// немного отступаем(так видно что нашли дистанцию)
goBackward();
delay(200);
stopMovement();
blinkLed();
return true;// возвращаем 1, т.к. сумели выполнить задачу
}
}
Serial.println("distance not found");
return false;// возвращаем ложь в случае неудачи
}
//это тестовая функция, узнаем какая скорость у робота
float getMySpeed(){
int secToMeas=2;
float firstDistance=getDistance();
goForward();
delay(secToMeas*1000);
stopMovement();
float newDistance=getDistance();
return (firstDistance-getDistance())/secToMeas/100;
}
//моргаем светодиодом
void blinkLed(){
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
}
float mySpeedSm=0;//скорость в см/c
float mySpeedM=0;// и в м/c
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
// т.к. на этот пин ничего не подключено мы получаем шум
// в качестве зерна генератора
randomSeed(analogRead(0));
// иницилизируем сенсор и моторы, делаем проверку
pinMode(ledPin, OUTPUT);
Serial.println("Testing systems");
blinkLed();
// настраиваем сенсор
getDistance();
if(getDistance()>0){
Serial.println("Ultrasonic sensor ready");
}
delay(1000/4);
// настраиваем моторы
motorL.setSpeed(255);
motorR.setSpeed(255);
stopMovement();
blinkLed();
delay(1000/3);
Serial.println("Getting averange speed");
blinkLed();
mySpeedSm=getMySpeed();
mySpeedM=mySpeedSm/100;
blinkLed();
blinkLed();
blinkLed();
}
int tries=MaxTries;
// основной цикл работы робота
void loop(){
// ищем максимум вокруг
int maxDist=getMaxDistanseAround();
Serial.print("Found max distance");
Serial.println(maxDist);
delay(500);
// пробуем повернуться на него
if(turnToDistance(maxDist)){
tries=MaxTries;// обнуляем счетчик попыток
int lastDistance=getDistance();
// едем до некого растояния вперед
while(lastDistance>MaxRange){
goForward();
delay(500);
// Проверка застряли или нет
int newDist=getDistance();
if(isInRange(newDist,lastDistance-2,lastDistance+2)){
goBackward();
delay(1000);
lastDistance=0;
}
else{
lastDistance=newDist;
}
}
}else{
// в случае невозможности выхода на максимальную
// уменьшаем счетчик попыток
tries--;
if(tries==0){// если попыток не осталось пробуем поехать хоть куда-нибудь
if(getDistance()>MaxRange*2){
goForward();
delay(1000);
}
else{
goBackward();
delay(1000);
}
}
}
stopMovement();
delay(500);
}
Видео
Заключение
За один вечер реально построить простейшего робота. Конечно же есть недоделки, например сенсор стоит повесить на сервомотор и провода следует привести в нормальный вид. Надеюсь вам понравится такой робот.