Содержание:
- Введение
- Видеопрезентация работы
- Шаг 1. Материалы и инструменты
- Шаг 2. Мозг
- Шаг 3. Сенсоры
- Шаг 4. Шасси
- Шаг 5. Программирование
- Шаг 6. Окончательная сборка
Введение:
Fijibot – это автономный самозаряжаемый робот, который будет самостоятельно искать источник света. Построить его можно с пластиковой 1,5 л бутылки (в инструкции указывается вода Fiji, но это не принципиально важно, можно использовать любую бутылку), контроллера Arduino Uno, 6-вольтной солнечной панели, колес и элементов управления из детской машинки на пульте управления.
Видеопрезентация работы:
Шаг 1. Материалы и инструменты:
Материалы:
- 1 – 1,5 л пластиковая бутылка
- 1 – старая разобранная машинка с дистанционным управлением
- 1 – комплект ПО Arduino Uno
- 1 – комплект Arduino Proto Shield
- 1 – набор отдельных соединяющих контактов
- 1 – набор перемычек Female/Female
- 1 – 6-вольтная солнечная панель
- 2 – сервоприводы непрерывного вращения Parallax
- 2 – стандартные серводвигатели Parallax 4-6VDC
- 1 – датчик столкновений Parallax Ping Sensor
- 1 – держатель для 4-ех батареек АА
- 1 – держатель для 9-вольтной батареи
- 4 – фоторезисторы
- 4 – держатели для светодиодов
- 4 – резисторы на 10K Ом
- 1 – микро 1А диод 1N4001.
Инструменты:
- паяльник
- припой
- вспомогательные устройства: зажимы, плоскогубцы
- устройства для зачистки проводов
- бокорезы
- дремель.
Микроконтроллер Arduino Uno для этого робота подходит больше всего, потому что это устройство создано для небольших проектов с программированием C + +.
Fijibot включает в себя четыре сервопривода: один с непрерывной работой каждого заднего колеса, один стандартный серводвигатель управляет головой робота с датчиками столкновения, а другой стандартный сервопривод предназначен для перемещения передней левой или правой оси при поворотах.
Учитывая, что весь механизм будет размещен внутри бутылки, нужно иметь возможность легко подключать и отключать все датчики, сервоприводы и т.д. от платы Arduino Proto Shield. Таким образом, нам понадобится системная плата Proto Shield и соединяющие контакты от Adafruit. Нужно припаять контакты к экрану Proto Shield и подключить все элементы перемычками.
В средней части плата имеет два параллельных канала, подключенных к +5 В и GND. Справа и слева от этих каналов находятся перпендикулярные панели с тремя концами. Нужно воспользоваться этим приспособлением для установки 5 отколовшихся контактов между двумя каналами и перпендикулярными панелями. В основном это даст энергию, опору и сигнальные толчки для каждого сервопривода и датчика. Затем нужно добавить 4 отдельных контакты к +5 В и сигнальным панелям для установки фоторезисторов.
Обратите внимание на фото, что контактные разъемы, которые шли с комплектом Proto Shield, не припаяны к аналоговым контактам или ко второй стороне цифровых выводов. Оставьте это просто так и припаяйте проводы непосредственно на панели.
Затем подключите провода к цифровым контактам PWM (для сервоприводов) и аналоговым контактам (для фоторезисторов). Также добавьте 10K резистор для каждого фоторезистора.
Также подключите провода от контактов 7 и 9 из платы Proto к положительным проводам зеленого и красного светодиодов соответственно.
Для того, чтобы управлять четырьмя сервоприводами и Arduino, нужно использовать два отдельных источника питания. Arduio работает на 9v батарее. Четыре сервоприводы и датчик столкновения работает на 4-ех AA батарейках, которые подключены параллельно к 6v солнечной панели для внутрисхемной зарядки. Так как солнечные панели и батареи тесно расположены друг к другу, нужно просто подключить диод между ними для предотвращения обратного тока.
Проверьте оба источника питания через переключатель DPST на полную мощность и оставьте солнечные панели подключенными к батареям AА. Такой способ может зарядить батареи робота, даже когда они не используются.
Шаг 3. Сенсоры:
Перемычки Adafruit продаются в одном наборе из 40 проводов. Все, что вам нужно сделать, это взять нужное количество проводов, и у вас будет хороший небольшой съемный кабель!
Когда фоторезисторы будут установлены на шасси с помощью держателей для светодиодов, нужно быстро и легко отсоединить их от платы во время и после конструкции. Так что просто подключите один конец перемычки female/female к каждому фоторезистору, а другой конец к контактам на плату Proto Shield. Резиновые прокладки в светодиодных держателях оберегают провода от прикосновения друг к другу и короткого замыкания.
Шаг 4. Шасси:
В этом шаге понадобится дешевая детская машинка с дистанционным управлением и большими колесами. Удалите все «лишние» части машинки и возьмите задние колеса и передок, включая колеса и подвес.
Используйте задние колеса для мощности, а передние колеса с подвесом для рулевого управления. Прикрепите два сервопривода непрерывного вращения к задней части бутылки с помощью двустороннего скотча. Используйте также скотч, чтобы обеспечить работу сервоприводов между собой. Затем вырежьте небольшое отверстие в пластиковой бутылке, чтобы питать энергией серводвигатели.
Для переднего конца приложите стандартную систему подвеса так, чтобы она могла повернуть передние колеса влево или вправо. Далее вырежьте прямоугольное отверстие в бутылке с четырьмя концами. Затем поместите сервопривода в проем, и закрепите в бутылке, используя 6/32 гаек и болтов.
На обратной стороне бутылки вырежьте клапан для того, чтобы удобно было работать внутри бутылки. Далее просверлите четыре 5/16 "отверстия в передней и задней сторонах бутылки и установите держатели для светодиодов.
Голова Fijibot имеет ультразвуковой датчик, который крепится к верхней части стандартного сервопривода. Нужно просверлить отверстие в верхней части бутылки для зубчатой передачи серводвигателя, чтобы он присоединился к датчику, а затем сделайте четыре отверстия для 6/32" болтов, чтобы надежно закрепить сервоприводы в бутылке.
Наконец, подключите все провода из клапана и обозначьте их соответственно для подключения к печатной плате.
Шаг 5. Программирование:
Основная миссия Fijibot в том, чтобы найти "пищу". Его пища – это свет для зарядки его батареи через солнечную панель. Используйте четыре фоторезисторы, установленные на держателях для светодиодов (спереди, справа, слева и сверху), чтобы помочь роботу найти самые яркие места в комнате. Основной цикл программы сравнивает значения из четырех резисторов и движется в сторону самого света. Когда робот находит яркое пятно, он останавливается и пользуется зарядкой.
В поисках света для зарядки своих батарей, Fijibot избегает столкновений с помощью ультразвукового датчика. Основной цикл программы постоянно проверяет препятствия в пределах указанного диапазона (30 дюймов). Если обнаружена помеха, Fijibot останавливается, смотрит налево и направо (с использованием стандартного сервопривода Parallax), и решает, в каком направлении ему нужно правильно двигаться. Если препятствие находится впереди, слева или справа, робот создаст резервную копию на полсекунды и попробует пройти снова.
Код программирования:
#include <servo.h>
//debug
bool show Readings = true;
bool showDirections = true;
bool seekLight = true;
bool avoidStuff = true;
//assign servos
Servo rightServo; //Digital Pin 7
Servo leftServo; //Digital Pin 12
Servo pingServo; //Digital Pin 11
Servo turnServo; //Digital Pin 10
//Ping
const int pingPin = 9;
const long minClearanceInches = 36;
const long minTurnClearance = 12;
bool clearPath = true;
bool rightClear = true;
bool leftClear = true;
bool tooCloseToTurn = false;
int backUpCount = 0;
//assign analog pins to photoresistors
const int frontSensorPin = 2;
const int rightSensorPin = 3;
const int leftSensorPin = 4;
const int topSensorPin = 5;
//assign digital pins
const int greenLED = 5;
const int redLED = 6;
//rear wheels
const int rotateLeft = 150;
const int rotateRight = 0;
const int fullStop = 90;
//light readings
int readings[4] = {0,0,0,0};
int highestReading = 0;
//looking
const int headRight = 0;
const int headLeft = 160;
const int headForward = 80;
//turning
const int turnRight = 75;
const int turnLeft = 102;
const int goStraight = 90;
void setup(void){
Serial.begin(9600);
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
rightServo.attach(7);
rightServo.write(fullStop); // initialize right servo
leftServo.attach(12);
leftServo.write(fullStop); //initialize left servo
pingServo.attach(11);
pingServo.write(80); // initialize Ping servo
turnServo.attach(10);
turnServo.write(90); // initialize turn servo
//delay on start; blink leds five times
for (int i = 0; i < 5; i++)
{
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, HIGH);
delay(500);
digitalWrite(greenLED, LOW);
digitalWrite(redLED, LOW);
delay(500);
}
}
void loop(void){
Serial.println("Top of Loop");
if (seekLight == true)
{
//read photoresistors
readings[0] = analogRead(frontSensorPin);
readings[1] = analogRead(rightSensorPin);
readings[2] = analogRead(leftSensorPin);
readings[3] = analogRead(topSensorPin);
highestReading = 0;
//display readings front, right, left, top and get highest
for (int i = 0; i < 4; i++)
{
if (showReadings == true) {Serial.print(readings[i]);}
if (readings[i] > readings[highestReading])
{
highestReading = i;
}
if (i < 3)
{
if (showReadings == true) {Serial.print(", ");}
}
else
{
if (showReadings == true) {Serial.println("");}
}
}
}
else
{
highestReading = 0;
}
if (highestReading != 3)
{
//check forward path
lookForward();
clearPath = pingBlocked() > minClearanceInches;
if (tooCloseToTurn)
{
highestReading = 4; //backup
}
else if (!clearPath)
{
if (readings[1] > readings[2] && lookRight() > minTurnClearance)
{
highestReading = 1; //turn right
}
else if (lookLeft() > minTurnClearance)
{
highestReading = 2; //turn left
}
else
{
highestReading = 4; //backup
}
lookForward();
}
}
//move toward light or unobstructed path
switch ( highestReading )
{
case 0 : //front
if (showDirections == true) {Serial.println("Go Forward");}
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, HIGH);
setMotors(rotateLeft, rotateRight, goStraight);
break;
case 1 : //right
if (lookRight() > minTurnClearance)
{
if (showDirections == true) {Serial.println("Turn Right");}
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, LOW);
backUpCount = 0;
lookForward();
setMotors(rotateLeft, rotateRight, turnRight);
delay(1000);
}
lookForward();
break;
case 2 : //left
if (lookLeft() > minTurnClearance)
{
if (showDirections == true) {Serial.println("Turn Left");}
digitalWrite(greenLED, LOW);
digitalWrite(redLED, HIGH);
backUpCount = 0;
lookForward();
setMotors(rotateLeft, rotateRight, turnLeft);
delay(1000);
}
lookForward();
break;
case 3 : //top
if (showDirections == true) {Serial.println("Stop");} //highest light level above; stop and bask
digitalWrite(greenLED, HIGH);
digitalWrite(redLED, HIGH);
setMotors(fullStop, fullStop, goStraight);
break;
case 4 : //backup
backUpCount++;
if (backUpCount < 2)
{
digitalWrite(greenLED, LOW);
digitalWrite(redLED, LOW);
if (showDirections == true) {Serial.println("Backup");}
setMotors(rotateRight, rotateLeft, goStraight);
delay(1000);
}
else
{
//if already backed up twice, try short right turn
backUpCount = 0;
setMotors(rotateLeft, rotateRight, turnRight);
delay(500);
}
break;
}
}
void setMotors(int left, int right, int turnPos)
{
if (showDirections == true) {Serial.println("Clear Path");}
turnServo.write(turnPos);
leftServo.write(left);
rightServo.write(right);
delay(20);
}
long pingBlocked()
{
long duration, distance;
//initialize Ping with LOW then HIGH
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
//read Ping
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
//convert microseconds to distance in inches
distance = microsecondsToInches(duration);
if (showReadings == true) {
Serial.print(duration);
Serial.print(", ");
Serial.println(distance);
}
//fix for no reading (distance = 0)
if (distance == 0)
{
distance = minClearanceInches;
}
//check for turn clearance
tooCloseToTurn = distance < minTurnClearance;
//compare to minClearanceInches
return distance;
}
long microsecondsToInches(long microseconds)
{
// The speed of sound is 13512 inches per second, which is 74 microseconds/in
// Sound travels out and back to the Ping, so find half the distance recorded
return microseconds / 74 / 2;
}
long lookRight()
{
//turn Ping to right
if (showDirections == true) {Serial.println("Look Right");}
pingServo.write(headRight);
delay(500);
return pingBlocked();
}
long lookLeft()
{
//turn Ping to left
if (showDirections == true) {Serial.println("Look Left");}
pingServo.write(headLeft);
delay(500);
return pingBlocked();
}
void lookForward()
{
//turn Ping to front
if (showDirections == true) {Serial.println("Look Forward");}
pingServo.write(headForward);
}
Шаг 6. Окончательная сборка:
Теперь можно попробовать соединить всё вместе и включить робота Fijibot. Сначала соедините перемычки от серводвигателей и сенсоров к штепсельным каналам на плате с микросхемой. Через клапан на бутылке, который остается открытым, прикрепите два аккумуляторы и разместите всё в бутылке, как следует (смотрите фото). Вы также можете использовать полоски Velcro для того, чтобы закрепить надежно плату с микросхемой и аккумуляторы внутри бутылки.
Наконец, установите колеса и солнечную панель. Ваш робот готов к испытаниям!
Настройте в помещении два разных источника цвета, а между ними поставьте помеху, например, мусорную корзину. Fijibot должен найти ближайший источник света и позиционировать себя под ним. Затем переместите свет и посмотрите, сможет ли робот найти источник, не столкнувшись с корзиной.