RT0008 — Робот на Arduino Uno

Опубликовал | 27.11.2015

Приветствую! Представляю обзор набора для самостоятельной сборки робота. Набор представляет собой платформу и набор модулей с деталями — все это при желании можно приобрести отдельно. Подробности, скетчи, проблемы при сборке, а также видео в работе смотрите далее.

Пришла коробка. Довольно большая. С дыркой.

Вес

Коробка пробита радиатором от модуля с L298N

Открываем

Для простоты восприятия информации и чтобы самому не путаться, я буду разбирать содержимое, параллельно рассказывать о нем, и собирать робота.

Основная платформа, к которой уже зачем-то прикрутили двигатели, кроватку под 2*18650 и модуль драйвера L298N. Сама платформа из прозрачного акрила. Достаточно толстая. Защитную бумагу отдирать не стал.

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

Драйвер шагового двигателя и двигателя постоянного тока L298N

Схема подключения

Про работу можно почитать например здесь

Двигатели постоянного тока. Питание от 3 до 12 вольт. Рекомендованное от 6 до 8 вольт.

Заднее колесо. На шарикоподшипнике.

Вставил в клеммники провода от движков.

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

Колеса. Просто одеваются на вал двигателя. При желании можно просверлить в центре отверстие и притянуть к валу саморезом.

Колеса на местах

Идем дальше. Шлейф. Должно быть 40 проводов мама-мама. Обычный, не лучше и не хуже тех что можно купить отдельно. В процессе сборки попались пара хреновых коннекторов.

Также в комплекте парочка говенных аккумов. Емкость где-то 500 mAh, сойдут как тестовые, не более.

Хороший кабель USB-miniUSB, только короткий.

Мозг нашего робота Funduino UNO

Отличие от обычной ардуины уно в том что для каждого аналогового и цифрового входа распаяны по три пина: сигнал-питание-земля. Благодаря чему можно повесить на плату множество внешних датчиков (серв, экранов) без использования сенсор-шилда. Также на плате есть переключатель питания 5 или 3.3 вольта. Подключение через миниUSB, а не через USB-b, что тоже довольно удобно.

контроллер ATmega 328p

Экран 1602 с синей подсветкой. Модуль IIC / I2C уже запаян. Благодаря чему дисплей будет проще подключать и регулировать контрастность.

Ультразвуковой датчик HC — SR04

Верхняя платформа. Сделана из черного акрила. Единственная деталь в наборе, которую будет проблематично найти отдельно в продаже. (хотя может просто плохо искал)

С нее бумагу решил убрать

Остальное.

Платформа для сервомотора

IR пульт

IR приемник

Сам сервик. Достаточно популярный SG90.

Колеса для оптических сенсоров. Видимо в комплекте с платформой.

Повесил чтоб не потерялись

Приступим к сборке.
Прикручиваю стойки к экрану.

Прикручиваем к платформе

Теперь прикрутим ардуину

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

Теперь прикручиваю стойки к платформе

И ставим на наше шасси

Теперь будем припиливать серву

Подвижная платформа рассчитана на использование с этими серводвигателями, поэтому все собирается без проблем. Сама платформа предназначена для двух сервомоторов — для движения в горизонтальной и вертикальной плоскостях. Вертикальное вращение нам без надобности, поэтому вставляем только один сервомотор.

Обкусываем крепление

Еще

Теперь влезает

Прикручиваю комплектными винтами

И крепим на шасси

Оставшиеся после сборки винтики, гайки и стойки.

Подключаем питание на двигатели и на драйвер

Подключаем драйвер к ардуине

Подключаем все остальное

Ультразвуковой сенсор сначала повесил на нижнюю рамку. Не фотал. При тестировании робота проявилась проблема (проблем на самом деле было много, но рассмотрю конкретную) Робот периодически начинал дебилировать, кружиться на месте и т.д.
Выяснил что в показания сенсора вносит помехи серводвигатель. Робот думает что впереди препятствии и выполняет алгоритм разворота. Не важно что и на каких входах висит, помехи есть даже если крутить отключенную серву. Сенсоры и сервы менял (имеются в запасе). Проблему решил подняв сенсор. Как раз использовал оставшееся детали от крепежа под вертикальный сервик.

ИК приемник прикрутил сзади

Готовый робот

Программа.
Скетч и мануал нашел на банггуде))) Саппорт давал ссылки на дропбокс
Я тоже их приведу www.dropbox.com/s/ao4rzw93iu3v5ox/SKU116898%20Remote%20control%20ultrasonic%20ranging%20smart%20car.rar
Там универсальная инструкция, библиотеки, примеры, сам скетч.
Библиотеки устаревшие и в Arduino 1.6.5. не работают. Скетч основной программы тоже так и не открылся.
Сам текст программы содержит достаточно много ошибок и опечаток.

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

Коды ик пульта были перепутаны, один код лишний, ничего на него не вешал, но и удалять не стал.
Сомнительная польза дисплея, на нем отображаются текущие действия (стоп, вперед, назад). Добавил немного текста и функцию очистки, а то все наслаивалось друг на друга.
Функцию регулирования скорости не реализовали, думаю вернуться к этому позже.
Еще уменьшил время поворота в два раза, потому что с исходными значениями робот поворачивал на слишком большой угол. Ну и так по мелочи, сильно ничего не менял.

скетч
#include <IRremote.h>
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int MotorRight1=8;
int MotorRight2=9;
int MotorLeft1=7;
int MotorLeft2=6;
int counter=0;

const int irReceiverPin = 2;
long IRfront=0x00FF629D; //Forward code
long IRback=0x00FFA857; //Backward
long IRturnright=0x00FFC23D;//Right
long IRturnleft=0x00FF22DD; //Left
long IRstop=0x00FF02FD; //Stop
long IRAutorun=0x00FF6897; //Ultrasonic Self-propelled mode
long IRturnsmallleft=0x00FFB04F;
IRrecv irrecv(irReceiverPin); // Define IRrecv thing receive IR signal
decode_results results;
int inputPin =A0; // define ultrasonic receive pin rx
int outputPin =A1; // define ultrasonic transmit pin tx
int Fspeedd = 0; // Front distance
int Rspeedd = 0; // right distance
int Lspeedd = 0; // left distance
int directionn = 0; // front=8 back=2 left=4 right=6
Servo myservo; // define myservo
int delay_time = 250; // servo turn back steady time
int Fgo = 8; // forward
int Rgo = 6; // right
int Lgo = 4; // left
int Bgo = 2; // backward

LiquidCrystal_I2C lcd(0x27,16,2);
void setup()
{
Serial.begin(9600);
pinMode(MotorRight1, OUTPUT); // pin8 (PWM)
pinMode(MotorRight2, OUTPUT); // pin9 (PWM)
pinMode(MotorLeft1, OUTPUT); //pin10 (PWM)
pinMode(MotorLeft2, OUTPUT); // pin11 (PWM)
irrecv.enableIRIn(); // Start infrared decoding
digitalWrite(3,HIGH);
pinMode(inputPin, INPUT); // define ultrasonic input foot
pinMode(outputPin, OUTPUT); // define ultrasonic output foot
myservo.attach(5); // define servo output to pin 5(PWM)
lcd.init(); // initialize the lcd
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print(«I’m CRAZY ROBOT»);
lcd.setCursor(0,1);
lcd.print(«Kill All Humans!»);
}
void advance(int a) // Forward
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,HIGH);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,HIGH);
delay(a * 100);
}
void right(int b) //right(Single wheel )
{
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,HIGH);
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
delay(b * 50);
}
void left(int c) //left (Single wheel)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,HIGH);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
delay(c * 50);
}
void turnR(int d) //right(double wheel)
{
digitalWrite(MotorRight1,HIGH);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,HIGH);
delay(d * 100);
}
void turnL(int e) //left(double wheel)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,HIGH);
digitalWrite(MotorLeft1,HIGH);
digitalWrite(MotorLeft2,LOW);
delay(e * 100);
}
void stopp(int f) //stop
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
delay(f * 100);
}
void back(int g) //backward
{
digitalWrite(MotorRight1,HIGH);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,HIGH);
digitalWrite(MotorLeft2,LOW);;
delay(g * 100);
}
void detection() //Measuring three angles (front,left,right)
{
int delay_time = 350; // servo turn back steady time
ask_pin_F(); // read forward distance
if(Fspeedd < 10) // If the forward distance is less than 10 cm
{
stopp(1); // Clear Output Data
directionn = Bgo; // backward 0.2 s

}
if(Fspeedd < 25) // If the forward distance is less than 25 cm
{
stopp(1); // Clear Output Data
ask_pin_L(); // read left distance
delay(delay_time); // wait servo steady
ask_pin_R(); // read right distance
delay(delay_time); // wait servo steady
if(Lspeedd > Rspeedd) //If left distance is more than right distance
{
directionn = Lgo; //Turn left
}
if(Lspeedd <= Rspeedd) //If left distance is less than or equal to right distance
{
directionn = Rgo; //Turn right
}
if (Lspeedd < 15 && Rspeedd < 15) //If left distance and right distance are less than 10cm
{
directionn = Bgo; //turn back
}
}
else //If front distance is more than 25cm
{
directionn = Fgo; //forward
}
}
void ask_pin_F() // measure front distance
{
myservo.write(96);
digitalWrite(outputPin, LOW); // Let ultrasonic transmitting low voltage 2us
delayMicroseconds(2);
digitalWrite(outputPin, HIGH); // Let ultrasonic transmitting high voltage 10us,here must at least 10us
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // keep ultrasonic transmitting low voltage
float Fdistance = pulseIn(inputPin, HIGH); // read time difference
Fdistance= Fdistance/5.8/10; // transfer time into distance(unit:cm)
Fspeedd = Fdistance; // read distance into Fspeedd(front speed)
}
void ask_pin_L() // measure left distance
{
myservo.write(170);
delay(delay_time);
digitalWrite(outputPin, LOW); // Let ultrasonic transmitting low voltage 2us
delayMicroseconds(2);
digitalWrite(outputPin, HIGH); // Let ultrasonic transmitting high voltage 10us,here must at least 10us
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // keep ultrasonic transmitting low voltage
float Ldistance = pulseIn(inputPin, HIGH); // read time difference
Ldistance= Ldistance/5.8/10; // transfer time into distance(unit:cm)
Lspeedd = Ldistance; // read distance into Lspeedd(left speed)
}
void ask_pin_R() // measure right distance
{
myservo.write(30);
delay(delay_time);
digitalWrite(outputPin, LOW); // Let ultrasonic transmitting low voltage 2us
delayMicroseconds(2);
digitalWrite(outputPin, HIGH); // Let ultrasonic transmitting high voltage 10us,here must at least 10us
delayMicroseconds(10);
digitalWrite(outputPin, LOW); // keep ultrasonic transmitting low voltage
float Rdistance = pulseIn(inputPin, HIGH); // read time difference
Rdistance= Rdistance/5.8/10; // transfer time into distance(unit:cm)
Rspeedd = Rdistance; // read distance into Rspeedd(right speed)
}
void loop()
{
if (irrecv.decode(&results))
{
if (results.value == IRfront)//forward
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«IR mode»);
lcd.setCursor(0,1);
lcd.print(«advance»);
advance(20);
}
if (results.value == IRback)//backward
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«IR mode»);
lcd.setCursor(0,1);
lcd.print(«back»);
back(20);//backward
}
if (results.value == IRturnright)//turn right
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«IR mode»);
lcd.setCursor(0,1);
lcd.print(«right»);
right(10); // turn right
}
if (results.value == IRturnleft)//turn left
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«IR mode»);
lcd.setCursor(0,1);
lcd.print(«left»);
left(10); // turn left
}
if (results.value == IRstop)//stop
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«IR mode»);
lcd.setCursor(0,1);
lcd.print(«stop»);
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
}
if (results.value ==IRAutorun )
{
while(IRAutorun)
{
myservo.write(90); //Let servo motor return, ready for the next measurement
detection(); //To measure the angle and determine which direction to move
if(directionn == 8)
{
if (irrecv.decode(&results))
{
irrecv.resume();
Serial.println(results.value,HEX);
if(results.value ==IRstop)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
break;
}
}
results.value=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«auto mode»);
lcd.setCursor(0,1);
lcd.print(«Advance»);
advance(1); // normal forward
}
if(directionn == 2) //If directionn(direction) = 2(backward)
{
if (irrecv.decode(&results))
{
irrecv.resume();
Serial.println(results.value,HEX);
if(results.value ==IRstop)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
break;
}
}
results.value=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«auto mode»);
lcd.setCursor(0,1);
lcd.print(«Reverse»);
back(8); // backward
turnL(2); //Move slightly to the left side, to prevent the dead alley
}
if(directionn == 6) //If directionn(direction) = 6(turn right)
{
if (irrecv.decode(&results))
{
irrecv.resume();
Serial.println(results.value,HEX);
if(results.value ==IRstop)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
break;
}
}
results.value=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«auto mode»);
lcd.setCursor(0,1);
lcd.print(«Right»);
back(1);
turnR(3); // turn rirht
}
if(directionn == 4) //directionn(direction) = 4(turn left)
{
if (irrecv.decode(&results))
{
irrecv.resume();
Serial.println(results.value,HEX);
if(results.value ==IRstop)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);

break;
}
}
results.value=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«auto mode»);
lcd.setCursor(0,1);
lcd.print(«Left»);
back(1);
turnL(3); // turn left
}
if (irrecv.decode(&results))
{
irrecv.resume();
Serial.println(results.value,HEX);
if(results.value ==IRstop)
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
break;
}
}
}
results.value=0;
}
else
{
digitalWrite(MotorRight1,LOW);
digitalWrite(MotorRight2,LOW);
digitalWrite(MotorLeft1,LOW);
digitalWrite(MotorLeft2,LOW);
}
irrecv.resume(); // Continue to receive the next set of infrared signals
}
}

Я качал много библиотек, не со всеми все получалось сразу. Например LiquidCrystal_I2C нашел рабочую только с третьего раза.
Поэтому даю ссылку на мою папку libraries

библиотеки

комплектные примеры

файл скетча

Так как заднее колесо вращается на 360 градусов, то это вносит немного рандома в движение робота.

Попробовал зафиксировать колесо стяжками — робот стал ездить более осознанно))

Видео работы

Итог: интересная игрушка. Есть возможность усовершенствовать сабж, повесить камеру, сделать фары. Можно даже замутить клешню. Место на платформе есть. Конструктором назвать сложно, скорее просто набор деталей. Проектов в сети много, как простых так и сложных. Можно купить подходящее шасси и придумывать уже свой проект. В общем ардуина есть ардуина)) Жаль только времени не хватает — вот если бы мне все это лет десять назад, эх… :)
Еще замечания по данному роботу: думаю что четырехколесная версия будет ездить лучше и четче. К тому же в старшей версии реализовано управление скоростью.
Или еще вариант без бестолкового дисплея и с питанием под АА.
www.gearbest.com/kits/pp_226901.html

Возможно что-то забыл. Если что, спрашивайте.

Спасибо за внимание!
Надеюсь обзор понравился и оказался полезным!

Товар предоставлен для написания обзора магазином. Обзор опубликован в соответствии с п.18 Правил сайта.

(c) 2015 Источник материала.

Рекламные ссылки