Evolved Robo Sapien

Kunal Mehan & Sagar Mandal

/media/uploads/sagarmandal/image2.jpg


Project Description

This project turns the Robosapien v1 into a Bluetooth controllable robot with an autonomous mode functionality. Users can use the Adafruit Bluefruit app to make the robot move forward, backward, turn etc. The app can also be used to initiate the autonomouse mode. To interface with Robosapien's internal microcontroller, an ARM Mbed was utilized. Mbed's internal code utilized three infra-red sensors to read the robot's surroundings and a bluetooth module to receive signals from user.


Parts Used


Pin Assignments

Adafruit BLE Board
MbedAdafruit BLE
VU (+5V)Vin
gndgnd
gndCTS
p27 (Serial RX)TXO
p28 (Serial TX)RXI
Sharp Analog Distance Sensor
MbedSensors
VU (+5V)Vin
gndgnd
p17, p18, p19Analog Inputs
Robosapien
MbedRobosapien
gndgnd
p20Analog Input

Note: Since the components use a large amount of current, we connect a 470uF capacitor between Ground Bus and VU Bus.
Note: To power the Mbed, a portable battery pack was utilized.

The pin assignments are visualized in Figure 2. below.


/media/uploads/sagarmandal/robosapiens_pin_assignments.png
Figure 1. The wiring diagram and pin assignments of all the components.

Connecting It All Together

The following figures show the arrangements of the components being utilized. They are all mounted on the robot's body.


/media/uploads/sagarmandal/robot_connections.png
Figure 2. A diagram depicting the setup of components on the robot body.

/media/uploads/sagarmandal/img_5001.jpg
Figure 3. Picture of the back of the robot showing the mbed and the wiring.

Underlying Algorithm

Basic Movement Functionality

The basic movement functionality works by using the Adafruit BLE Board. The program accepts command from the smartphone connected to the BLE board. After receiving the command, it executes them. To perform activities like move forward, it first checks the relevant sensor so that it does not run into obstacles. It roars if it cannot move in a certain direction.

Autonomous Movement Functionality

In autonomous mode, the robot moves forward by default.
It checks the distance to the nearest obstacle and if it is over the limit of 20cm, it keeps walking forward.
If it detects and obstacle which is less than 20cm away, it takes a backward step.
It then checks the right sensor.
If distance reading on the right sensor is more than 20cm, it turns right.
After turning right, it resumes walking forward.
If right sensor reading is less than 20cm, it checks the left sensor. If left sensor reading is more than 20cm, it turns left and resumes walking forward in that direction.
If left sensor reading is less than 20cm, it keeps moving backward until either the left and right sensor gives a reading of more than limit (20cm).
When the sensors give such reading, it turns left or right, and keeps moving forward in that direction.

Code

main.cpp

#include "mbed.h"

#define  turnright              0x80
#define  rightarmup             0x81
#define  rightarmout            0x82
#define  tiltbodyright          0x83
#define  rightarmdown           0x84
#define  rightarmin             0x85
#define  walkforward            0x86
#define  walkbackward           0x87
#define  turnleft               0x88
#define  leftarmup              0x89
#define  leftarmout             0x8A
#define  tiltbodyleft           0x8B
#define  leftarmdown            0x8C
#define  leftarmin              0x8D
#define  stop                   0x8E
#define  rightturnstep          0xA0
#define  righthandthump         0xA1
#define  righthandthrow         0xA2
#define  sleep                  0xA3
#define  righthandpickup        0xA4
#define  leanbackward           0xA5
#define  forwardstep            0xA6
#define  backwardstep           0xA7
#define  leftturnstep           0xA8
#define  lefthandthump          0xA9
#define  lefthandthrow          0xAA
#define  listen                 0xAB
#define  lefthandpickup         0xAC
#define  leanforward            0xAD
#define  reset                  0xAE
#define  Execute                0xB0
#define  Wakeup                 0xB1
#define  Right                  0xB2
#define  Left                   0xB3
#define  Sonic                  0xB4
#define  righthandstrike3       0xC0
#define  righthandsweep         0xC1
#define  burp                   0xC2
#define  righthandstrike2       0xC3
#define  high5                  0xC4
#define  righthandstrike1       0xC5
#define  bulldozer              0xC6
#define  oopsfart               0xC7
#define  lefthandstrike3        0xC8
#define  lefthandsweep          0xC9
#define  whistle                0xCA
#define  lefthandstrike2        0xCB
#define  talkback               0xCC
#define  lefthandstrike1        0xCD
#define  roar                   0xCE
#define  AllDemo                0xD0
#define  PowerOff               0xD1
#define  Demo1                  0xD2
#define  Demo2                  0xD3
#define  Dance                  0xD4
#define  RSNoOp                 0xEF

DigitalOut IROut(p20, 1);
AnalogIn IRSensor_left(p17);
AnalogIn IRSensor_right(p18);
AnalogIn IRSensor_front(p19);
BusOut myled(LED1,LED2,LED3,LED4);
Serial blue(p28,p27);
Serial pc(USBTX, USBRX);

float limit = 60;
int bitTime=516;       // Bit time (Theoretically 833 but as low as 516 may work)

void RSSendCommand(int command)
{
    IROut = 0;
    wait_us(8*bitTime);
    for (int i=0;i<8;i++) {
        IROut = 1;
        wait_us(bitTime);
        if ((command & 128) !=0) wait_us(3*bitTime);
        IROut = 0;
        wait_us(bitTime);
        command = command << 1;
    }
    IROut = 1;
    wait(0.20); // Give a 2 sec before next
}

float left_IR()
{
    float a = 1-IRSensor_left;
    return (a*100);
}

float right_IR()
{
    float a = 1-IRSensor_right;
    return (a*100);
}

float front_IR()
{
    float a = 1-IRSensor_front;
    return (a*100);
}

void autonomous_mode()
{
    while (1)
    {
        if (front_IR()<= limit)
        {
            while(front_IR()<=limit)
            {
                RSSendCommand(backwardstep);
                wait(2);
            }
            if (right_IR()>=limit)
            {
                RSSendCommand(rightturnstep);
                RSSendCommand(rightturnstep);
                RSSendCommand(rightturnstep);
                wait(3.5);
                RSSendCommand(stop);
            }
            else if (left_IR()>=limit)
            {
                RSSendCommand(leftturnstep);
                RSSendCommand(leftturnstep);
                RSSendCommand(leftturnstep);
                wait(3.5);
                RSSendCommand(stop);
            }
            else
            {
                while( left_IR()>=limit || right_IR()>=limit)
                {
                    RSSendCommand(backwardstep);
                }
                if(right_IR()>=limit)
                {
                    RSSendCommand(rightturnstep);
                    RSSendCommand(rightturnstep);
                    RSSendCommand(rightturnstep);
                    wait(3.5);
                    RSSendCommand(stop);
                }
                else if(left_IR()>=limit)
                {
                    RSSendCommand(leftturnstep);
                    RSSendCommand(leftturnstep);
                    RSSendCommand(leftturnstep);
                    wait(3.5);
                    RSSendCommand(stop);
                }
            }
        }
        else
        {
            RSSendCommand(forwardstep);
        }
    }
}

int main()
{
    RSSendCommand(burp);
    wait(2);
    RSSendCommand(high5);
    wait(5);
    char bnum=0;
    char bact=0;
    while(1)
    {
        if (blue.getc()=='!')
        {
            if (blue.getc()=='B')
            {
                bnum = blue.getc();
                if (bnum == '1')
                {
                    autonomous_mode();
                }
                else if (bnum == '5')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        if (front_IR() >= limit)
                            RSSendCommand(forwardstep);
                    }
                }
                else if (bnum == '6')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        RSSendCommand(backwardstep);
                    }
                }
                else if (bnum == '7')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        if (left_IR() >= limit)
                            RSSendCommand(leftturnstep);
                        else
                            RSSendCommand(roar);
                    }
                }
                else if (bnum == '8')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        if (right_IR() >= limit)
                            RSSendCommand(rightturnstep);
                        else
                            RSSendCommand(roar);
                    }
                }
                else if (bnum == '2')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        if ((left_IR() >= limit) &&
                            (right_IR() >= limit) && (front_IR() >= limit))
                        {
                            RSSendCommand(AllDemo);
                        } else
                            RSSendCommand(roar);
                    }
                }
                else if (bnum == '3')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        RSSendCommand(Dance);
                    }
                }
                else if (bnum == '4')
                {
                    bact = blue.getc();
                    if (bact == '1')
                    {
                        RSSendCommand(listen);
                        wait(4);
                        RSSendCommand(talkback);
                    }
                }
            }
        }
    }
}


Videos

Basic Movement Functionality

Autonomous Movement Functionality


Issues

  • The IR Sensor does not work very well in sun lit areas. The differences in reflectiveness of obstructing surfaces also results in obstruction being detected in different moments.
  • There were plans to integrate the autonomous mode in a way so that user could switch in and out of it using Bluetooth command. To do that, RTOS and Serial Interrupt was tested. However it was discovered:
    • Robot's IR control does not work too well with the RTOS code, due to waits.
    • Serial Interrupt does not work too well with it either.
  • Depending on the amount of power the portable battery pack and the stack space available, the angle per each turn command changes.

Possible Improvements

  • The project could be improved on by getting the robot to follow voice commands. This could be done by using Amazon Echo.
  • A larger and more accurate sensor array can be used to aid in movement. Possibly using multiple types of sensor.


Please log in to post comments.