Содержание:

 

  1. Введение
  2. Видеопрезентация работы
  3. Шаг 1. Материалы и инструменты
  4. Шаг 2. Мозг
  5. Шаг 3. Сенсоры
  6. Шаг 4. Шасси
  7. Шаг 5. Программирование
  8. Шаг 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.

Инструменты:

 

 

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

 


Шаг 2. Мозг:

Микроконтроллер 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 должен найти ближайший источник света и позиционировать себя под ним. Затем переместите свет и посмотрите, сможет ли робот найти источник, не столкнувшись с корзиной.