Project 14 4 in 1 Complete Robot

1.Overview

In the above projects, we have introduced four functions for the turtle robot, that is, line following, avoiding obstacles, IR control and Bluetooth remote control.

Now, let’s combine those functions together to make a complete robot. You can use the IR module to switch the functions.

2.Function switching methods

Powered on and aligned with the IR receiver, press the number 1 on the IR remote control, the turtle robot will enter the line tracking function. Then press the key OK, it will exist the tracking function.

  • If press the number 2, enter the obstacle avoidance function, and press OK to end that function.

  • If press the number 3, enter the S line forward, and press OK to end the function.

  • If press the number 4, the robot will turn around the wheel on the left, and press OK to end the function.

  • If press the number 5, the robot will turn a circle to the left, and press OK to end the function.

  • If press the number 6, the robot will turn a circle to the right, and press OK to end the function.

When exist the function modes, be able to control the car through infrared control or Phone-Bluetooth control.

3.Hookup Guide

4.Test Code 18

// dot matrix
#include <Wire.h>   // add IIC file
#include "Adafruit_LEDBackpack.h" 
#include "Adafruit_GFX.h"
Adafruit_LEDBackpack matrix = Adafruit_LEDBackpack();   // build an object to control the dot matrix

// IR receiver
#include <IRremote.h>    // add the IR receiver libraries
int RECV_PIN = A0;        // define the IR receiver pin as A0
IRrecv irrecv(RECV_PIN);
decode_results results;
// decoding of IR remote control
const long IR_front = 0x00FF629D;
const long IR_back = 0x00FFA857;
const long IR_left = 0x00FF22DD;
const long IR_right = 0x00FFC23D;
const long IR_stop = 0x00FF02FD;
const long IR_1 = 0x00FF6897;
const long IR_2 = 0x00FF9867;
const long IR_3 = 0x00FFB04F;
const long IR_4 = 0x00FF30CF;
const long IR_5 = 0x00FF18E7;
const long IR_6 = 0x00FF7A85;
const long IR_7 = 0x00FF10EF;
const long IR_8 = 0x00FF38C7;
const long IR_9 = 0x00FF5AA5;
const long IR_0 = 0x00FF52AD;

// line following 
const int S1 = 8;  // the S1 tracking sensor control pin to D8
const int S2 = 7;  // the S2 tracking sensor control pin to D7
const int S3 = 6;  // the S3 tracking sensor control pin to D6
int s1,s2,s3;   // define 3 variables,separately used to receive the digital value read by 3 tracking sensors(0 or 1)

// avoiding obstacles
const int servopin=3;// define the digital 3 to connect to servo signal line
//int myangle;// define the angle
//int pulsewidth;// define the pulsewidth 
#include <SR04.h>    // add the ultrasonic libraries 
#define TRIG_PIN 12   // define the pin ting of ultrasonic as D12
#define ECHO_PIN 13   //  define the pin echo of ultrasonic as D13
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);    // build an object to control the ultrasonic
long a,a1,a2;      // used to receive the distance measured by ultrasonic
// end the obstacle avoidance

// control two motors 
#define INT_A 2    // control the left motor direction pin as D2
#define INT_B 4    // control the right motor direction pin as D4
#define left_A 9    // control the left motor speed pin as D9
#define right_B 5   //control the right motor direction pin as D5 


long val;       // define a variable to receive the signal from IR transmitter
int i=0;

void setup() 
{ 
  Serial.begin(9600);           // set the baud rate of serial monitor to 9600
  irrecv.enableIRIn();            // Start the receiver
  delay(100);           // delay 100ms
  pinMode(INT_A,OUTPUT);           // set the motor control pin as OUTPUT
  pinMode(INT_B,OUTPUT);
  pinMode(left_A,OUTPUT);
  pinMode(right_B,OUTPUT);

  // DOT matrix
  matrix.begin(0x70);  // pass in the address
  chushi();         // initial matrix display 

  pinMode(servopin,OUTPUT);// set the servo pin as OUTPUT 
   // make the ultrasonic turn front 
  for(int i=0;i<=100;i++) // give enough time to servo to rotate to specific angle
  {
      digitalWrite(servopin,HIGH);// set the servo pin to HIGH 
      delayMicroseconds(1200);// delay the microseconds of pulsewidth 
      digitalWrite(servopin,LOW);// set the servo pin to LOW 
      delayMicroseconds(18800);// delay the microseconds of pulsewidth
  }
}

void loop() 
{
  i=1;
  Bluetooth();     // Bluetooth control
  if(irrecv.decode(&results))   // if receive the infrared signal 
  {
    val = results.value;      // assign the result to val
    Serial.println(val,HEX);    // print out the hexadecimal val value on the monitor
    
    irrecv.resume();    // Receive the next value
 }
 switch(val)   // perform the corresponding function for the data received
    {
      case  IR_front:  front(),qian();  break;   // go front and display the front image //if val equals to IR_front(IR_front=0x00FF629D),perform front() and qian() these two subfunctions,break statement is used to exist the current function
      case  IR_back:  back(),hou();    break;    // backward and show the back image
      case  IR_left:  left(),zuo();    break;    // turn left and show the left image
      case  IR_right:  right(),you();   break;   // turn right and show the right image
      case  IR_stop:  Stop(),ting();   break;    // stop and show the stop image
      case  IR_1:  xunji(),val=0;   break;       // enter the tracking function( press stop to end the function)
      case  IR_2:  bizhang(),val=0;   break;     // enter the obstacle avoiding function( press stop to end the function)
      case  IR_3:  left_l(),ZZ();  break;        // turn around the wheel on the left 
      case  IR_4:  right_run(),YX();   break;    // turn around to the right 
      case  IR_5:  front_s();  break;        // go front in S line and display S image 
      case  IR_6:  left_run(),ZX();   break;    //  turn around to the left
      default : printf("error");  
    }

}

// go front
void front()
{
    digitalWrite(INT_A,LOW);    // control the left motor turn forward 
    digitalWrite(INT_B,LOW);   // control the right motor turn forward 
    analogWrite(left_A,200);   // set the two motors’ speed (PWM=200)
    analogWrite(right_B,200);
}
// go backward
void back()  
{
  digitalWrite(INT_A,HIGH);   //  control the left motor turn backward 
  digitalWrite(INT_B,HIGH);    // control the right motor turn backward  
  analogWrite(left_A,200);   // set the two motors’ speed(PWM=200)
  analogWrite(right_B,200);
}
// turn left
void left()
{
  digitalWrite(INT_A,HIGH);    // control the left motor turn backward 
  digitalWrite(INT_B,LOW);    // control the right motor turn forward  
  analogWrite(left_A,150);    //  set the two motors’ speed(PWM为150)
  analogWrite(right_B,150);
}
//turn right 
void right()
{
  digitalWrite(INT_A,LOW);     //  control the left motor turn forward
  digitalWrite(INT_B,HIGH);     //  control the right motor turn backward
  analogWrite(left_A,150);    //  set the two motors’ speed(PWM为150)
  analogWrite(right_B,150);
}
// stop
void Stop()
{
  digitalWrite(INT_A,LOW);  
  digitalWrite(INT_B,LOW);
  analogWrite(left_A,0);    // both PWM are 0
  analogWrite(right_B,0);
}
// turn around the wheel on the left 
void left_l()
{
    digitalWrite(INT_A,HIGH);   // control the left motor turn backward 
    digitalWrite(INT_B,LOW);   // control the right motor turn forward 
    analogWrite(left_A,0);     //left PWM=0,means that the left wheel stops 
    analogWrite(right_B,255);    //right PWM=255,right wheel goes forward 
}
// turn around to the right
void right_run()
{
    digitalWrite(INT_A,LOW);    //control the left motor turn forward 
    digitalWrite(INT_B,LOW);   //  control the right motor turn forward 
    analogWrite(left_A,255);   // left motor PWM=255
    analogWrite(right_B,100);   // right motor PWM=100 
}
// turn around to the left
void left_run()
{
    digitalWrite(INT_A,LOW);    // control the left motor turn forward
    digitalWrite(INT_B,LOW);   // control the right motor turn forward 
    analogWrite(left_A,200);   // left motor PWM=100
    analogWrite(right_B,100);   // right motor PWM=200 (turn a circle to the left)
}

// go front in S line
void front_s()
{
    S();
  while(i>0)
  {
    digitalWrite(INT_A,LOW);   // control the left motor turn forward 
    digitalWrite(INT_B,LOW);   // control the right motor turn forward
    analogWrite(left_A,50);   // left motor PWM=100
    analogWrite(right_B,255);  // right motor PWM=255  ( walk in curved line to the left)
    delay(300);      //delay 1 second
    analogWrite(left_A,255);   //left motor PWM=255   
    analogWrite(right_B,50);  //right motor PWM=100  ( walk in curved line to the right )
    delay(300);      //delay 1S
    if(irrecv.decode(&results))   // if receive the infrared signal 
    {
      irrecv.resume();    // Receive the next value
      val=results.value;    // assign the received data to val
      if(val==IR_stop)   // if receive the stop command 
      {
        Stop();       // stop 
        break;        // end the current function 
      }
    }
  }
}
////////////////////////matrix display image////////////////////////////
// front image 
void qian()
{
    matrix.displaybuffer[3] = B11111111;     
    matrix.displaybuffer[4] = B11111111;
    matrix.displaybuffer[2] = B00000001;
    matrix.displaybuffer[1] = B00000010;
    matrix.displaybuffer[0] = B00000100;
    matrix.displaybuffer[5] = B00000001;
    matrix.displaybuffer[6] = B00000010;
    matrix.displaybuffer[7] = B00000100;
    matrix.writeDisplay();
}
// back image 
void hou()
{
    matrix.displaybuffer[3] = B11111111;
    matrix.displaybuffer[4] = B11111111;
    matrix.displaybuffer[2] = B00100000;
    matrix.displaybuffer[1] = B00010000;
    matrix.displaybuffer[0] = B00001000;
    matrix.displaybuffer[5] = B00100000;
    matrix.displaybuffer[6] = B00010000;
    matrix.displaybuffer[7] = B00001000;
    matrix.writeDisplay();
}
//right image 
void you()
{
    for(int i=0;i<8;i++)
    {
      matrix.displaybuffer[i] = B00001100;
    }
    matrix.displaybuffer[6] = B00011110;
    matrix.displaybuffer[5] = B00101101;
    matrix.displaybuffer[4] = B11001100;
    matrix.writeDisplay();
}
// left image 
void zuo()
{
    for(int i=0;i<8;i++)
    {
      matrix.displaybuffer[i] = B00001100;
    }
    matrix.displaybuffer[1] = B00011110;
    matrix.displaybuffer[2] = B00101101;
    matrix.displaybuffer[3] = B11001100;
    matrix.writeDisplay();
}
// stop image 
void ting()
{
    matrix.displaybuffer[0] = B11000000;
    matrix.displaybuffer[1] = B00100001;
    matrix.displaybuffer[2] = B00010010;
    matrix.displaybuffer[3] = B00001100;
    matrix.displaybuffer[4] = B00001100;
    matrix.displaybuffer[5] = B00010010;
    matrix.displaybuffer[6] = B00100001;
    matrix.displaybuffer[7] = B11000000;
    matrix.writeDisplay();
}
// initial display 
void chushi()
{
   for(int i=0;i<8;i++)
   {
    matrix.displaybuffer[i] = B10101010;
    matrix.writeDisplay();
    delay(100);
   }
}

//turn around the wheel on the left 
void ZZ()
{
    matrix.displaybuffer[0] = B00000000;
    matrix.displaybuffer[1] = B10000011;
    matrix.displaybuffer[2] = B11000001;
    matrix.displaybuffer[3] = B10100010;
    matrix.displaybuffer[4] = B00010100;
    matrix.displaybuffer[5] = B00001000;
    matrix.displaybuffer[6] = B00000000;
    matrix.displaybuffer[7] = B00000000;
    matrix.writeDisplay();
}
//turn around to the left 
void ZX()
{
    matrix.displaybuffer[0] = B00000000;
    matrix.displaybuffer[1] = B00011100;
    matrix.displaybuffer[2] = B00100010;
    matrix.displaybuffer[3] = B01000001;
    matrix.displaybuffer[4] = B00000001;
    matrix.displaybuffer[5] = B00111001;
    matrix.displaybuffer[6] = B00110010;
    matrix.displaybuffer[7] = B00101100;
    matrix.writeDisplay();
}
//turn around to the right 
void YX()
{
    matrix.displaybuffer[0] = B00001100;
    matrix.displaybuffer[1] = B00110010;
    matrix.displaybuffer[2] = B00111001;
    matrix.displaybuffer[3] = B00000001;
    matrix.displaybuffer[4] = B00000001;
    matrix.displaybuffer[5] = B00100010;
    matrix.displaybuffer[6] = B00011100;
    matrix.displaybuffer[7] = B00000000;
    matrix.writeDisplay();
}
//S line 
void S()
{
    matrix.displaybuffer[0] = B00000000;
    matrix.displaybuffer[1] = B00000000;
    matrix.displaybuffer[2] = B00110001;
    matrix.displaybuffer[3] = B11001000;
    matrix.displaybuffer[4] = B11000100;
    matrix.displaybuffer[5] = B00100011;
    matrix.displaybuffer[6] = B00000000;
    matrix.displaybuffer[7] = B00000000;
    matrix.writeDisplay();
}

//*******************************line tracking*******************************//
void xunji()
{
  while(val)
  {
    s1 = digitalRead(S1); // assign the digital value read from S1,S2,S3 pin to s1,s2,s3
    s2 = digitalRead(S2);
    s3 = digitalRead(S3);
    if(s2==1)  // if s2 pin detects a black line
    {
      if(s3==1 && s1==0)  // if s3 detects a black line,s1 not detect
      {
        left();     // turn left
      }
      else if(s3==0 && s1==1)  // if s3 not detect, but s1 detects
      {
        right();   // turn right
      }
      else      // or else 
      {
        front();   // go front
      }
    }

    else  //s2 not detect a black line 
    {
      if(s3==1&&s1==0)  // if s3 detects a black line 
      {
        left();     // turn left
      }
      else if(s3==0&&s1==1)  //s1 detects a black line 
      {
        right();    // turn right
      }
      else  // none detects a black line
      {
        Stop();      // stop
      }
    }
    if(irrecv.decode(&results))   // if receive the infrared signal
    {
      irrecv.resume();    // Receive the next value
      val=results.value;    // assign the received data to val
      if(val==IR_stop)   // if receive the stop command
      {
        Stop();       //stop
        break;        // exist the current function 
      }
    }
  }
}
//************************* end tracking********************************//

//******************************* avoiding obstacles *****************************//
void bizhang()
{
  while(val)
  {
     a=sr04.Distance();    // assign the front distance measured by ultrasonic to a
     Serial.print(a);     // print out the value a on the serial monitor
     Serial.println("cm");   // print out cm and line wrap
     delay(100);    //delay 
     if(a<15)    // if a is less than 15cm, yes to perform the program in the brace below
     {
      Stop();    // stop
      delay(100);   //delay 100ms
      //servopulse(servopin,160);// call the pulse function to make the ultrasonic turn right in 90 degrees
      // make the ultrasonic turn left in 90 degrees 
      for(int i=0;i<=100;i++) // give servo enough time to rotate to the specific angle
      {
          digitalWrite(servopin,HIGH);// set the servo pin to HIGH 
          delayMicroseconds(600);// the microseconds to delay plusewidth
          digitalWrite(servopin,LOW);// set the servo pin to LOW
          delayMicroseconds(19400);// the microseconds to delay plusewidth
      }
      
      a1=sr04.Distance();  // assign the left obstacle distance measured by ultrasonic to a1
      Serial.print("a1 = ");  // on the serial monitor print out a1 = 
      Serial.print(a1);      // print out the value of a1
      Serial.println("cm");   // print out cm and line wrap
      delay(100);    // delay 100ms
      //servopulse(servopin,20);//call the pulse function to make the ultrasonic turn left in 90 degrees
      //make the ultrasonic turn right in 90 degrees 
      for(int i=0;i<=300;i++) // give servo enough time to rotate to the specific angle 
      {
          digitalWrite(servopin,HIGH);// set the servo pin to HIGH 
          delayMicroseconds(1800);//the microseconds to delay pulsewidth
          digitalWrite(servopin,LOW);// set the servo pin to LOW
          delayMicroseconds(18200);// the microseconds to delay pulsewidth
      }
      
      a2=sr04.Distance();      // assign the right obstacle distance measured by ultrasonic to a2
      Serial.print("a2 = ");
      Serial.print(a2);
      Serial.println("cm");
      delay(100);
      if(a1<a2)     //if a1 is greater than a2(whether left distance is greater than  right one)
      {
       // servopulse(servopin,90);// call the pulse function to make the ultrasonic turn front
      //  make the ultrasonic turn front
      for(int i=0;i<=200;i++) // give servo enough time to rotate to the specific angle 
      {
          digitalWrite(servopin,HIGH);// set the servo pin to HIGH  
          delayMicroseconds(1200);// the microseconds to delay pulsewidth 
          digitalWrite(servopin,LOW);//  set the servo pin to LOW
          delayMicroseconds(18800);// the microseconds to delay pulsewidth 
      }
        left();    // TURN LEFT
        delay(370);   // delay 370ms,the time for car to turn left in 90 degrees as much as possible 
        front();  // go front
      }
      else     // if a1<a2
      {
        //servopulse(servopin,90);// call the pulse function to make the ultrasonic turn front
        // make the ultrasonic turn front 
        for(int i=0;i<=100;i++) // give servo enough time to rotate to the specific angle 
        {
        digitalWrite(servopin,HIGH);// set the servo pin to HIGH  
        delayMicroseconds(1200);// the microseconds to delay pulsewidth
        digitalWrite(servopin,LOW);// set the servo pin to LOW
        delayMicroseconds(18800);// the microseconds to delay pulsewidth 
        }
        right();  // TURN RIGHT 
        delay(370);  // delay 370ms,the time for car to turn right in 90 degrees as much as possible
        front();   // go front
      }
     }
     else   // if a>15cm
     {
      front();   // continue to go forward
     }
     if(irrecv.decode(&results))   // if receive the infrared signal
    {
      irrecv.resume();    // Receive the next value
      val=results.value;    // assign the infrared data received to val
      if(val==IR_stop)   // if it is stop key
      {
        Stop();    // stop
        break;     // exist the current function
      }
    }
  }
   
}

/*// servo
void servopulse(int servopin,int myangle)// define a pulse function
{
  for(int i=0;i<50;i++)
  {
    pulsewidth=(myangle*11)+500;// convert the angle into pulsewidth of 500-2480 
    digitalWrite(servopin,HIGH);// set the servo pin to HIGH 
    delayMicroseconds(pulsewidth);// the microseconds to delay pulsewidth 
    digitalWrite(servopin,LOW);// set the servo pin to LOW
    delay(20-pulsewidth/1000);
  }

}*/
//*******************************end the obstacle avoiding function*********************************//

//*******************************Bluetooth*************************************//
void Bluetooth()
{
  int temp;    // define the variable, used to receive the data read by Bluetooth
  if(Serial.available())     // if receive the data 
  {
    temp = Serial.read();       // assign the data received to temp
  }
  switch(temp)    // perform the corresponding function for the data received
  {
    case 'U':  front(),qian();  break;   // if val equals to U,perform front() and qian() subfunction,break statement means that exist the current function if receive other data.
    case 'D':  back(),hou();   break;
    case 'L':  left(),zuo();   break;
    case 'R':  right(),you();  break;
    case 'S':  Stop(),ting();   break;
    default : printf("error");  
  }

}

5.Example Result

Done uploading the above code to control board, turn on the POWER button on the shield, then open APP, connect to Bluetooth, you should see the LED on the Bluetooth module is normally on.

Then use an IR remote control to select the function modes to make the robot run freely, showing the state image on the dot matrix display.