Project showcase
Bluetooth controlled car with arduino mega

Bluetooth controlled car with arduino mega © GPL3+

you can remotely control your car with Bluetooth. Four settings are available: manual, automatic, steering and vocal control.

  • 1,661 views
  • 2 comments
  • 8 respects

Components and supplies

Apps and online services

About this project

  • About this project

I want to control a car, with one software in different ways. For this I use the bluetooth and an APP written with MIT, which allow me to control it in:

1) manual mode, using the directional arrows.

2) automatic mode, using the proximity sensor.

3) voice mode, using google speech recognition.

4) Steering mode, using the orientation sensor of the TABLET.

5) I'm working on the next command mode, it will use a GPS sensor connected to the arduino board. Using the GPS of the tablet,the car will be able to follow the tablet.

In the attachments are available the sources for the Arduino IDE and for MIT App inventor 2.

Automati control

Progress control via the pitch and roll orientation-sensor in TABLET

Vocal Control

Manual Control

Screenshot APK

Code

Arduino IDEArduino
#include <Servo.h>
#include <AFMotor.h>
#include <NewPing.h>

#define TRIG_PIN_A 41 
#define ECHO_PIN_A 40 
#define ECHO_PIN_R 39
#define TRIG_PIN_R 38  
#define MAX_DISTANCE 300
#define SENSORE_AVANTI 0
#define SENSORE_INDIETRO 1 
#define RIDUZIONE_POTENZA_LOW 2
#define DIR_INDIETRO 0
#define DIR_AVANTI 1
#define DIR_STOP 2
#define DIR_DESTRA 3
#define DIR_SINISTRA 4

/* Definizione Comandi ricevuti dall'App */
#define ARRESTA           48
#define AVANTI            49
#define INDIETRO          50
#define DESTRA            51
#define SINISTRA          52
#define DESTRA_AVANTI     53
#define SINISTRA_AVANTI   54
#define DESTRA_INDIETRO   55
#define SINISTRA_INDIETRO 56
#define ACCELLERA         57
#define DECELERA          58
#define AUTOMATICO        59
#define STOP              79
#define POTENZA           80
#define SETTING           90
NewPing sonar[2] = {
  NewPing(TRIG_PIN_A, ECHO_PIN_A, MAX_DISTANCE),
  NewPing(TRIG_PIN_R, ECHO_PIN_R, MAX_DISTANCE)
  };
AF_DCMotor motore_anteriore_dx(2);
AF_DCMotor motore_anteriore_sx(3);
AF_DCMotor motore_posteriore_sx(4);
AF_DCMotor motore_posteriore_dx(1);
Servo MyServo;
Servo MyServo_Info;

int direzione;
int potenza;
int bytericevuto = 0;
String cPotenza;
String cDistanza;
String cVelocita;
int pin_velocita = 20;
unsigned int cm_al_secondo; 
volatile unsigned int pulses;
unsigned long timeold;
unsigned long timeold2;
unsigned int pulsesperturn = 20;
int Dist_Sinistra      = 0;
int Dist_Destra        = 0;
int Dist_Avanti        = 0;
int Dist_Dietro        = 0;
int Dist_Sinistra_Diag = 0;
int Dist_Destra_Diag   = 0;
boolean DestraSinistra = false;
int Gradi              = 0;
int nX;
int Distanza_Frontale  = 30;
int Distanza_Laterale  = 20;
int Distanza_Minima    = 50;
int Potenza_Automatico = 65;
int Potenza_Minima     = 50;
int Accelera_Decelera  = 5;
int offset             = 5;
int Tempo_Rotazione    = 200;
int variabile = 0;


/* ---------- Interupt1----------------- */
void counter()  {
  pulses++;
}

/* ---------- Setup -------------------- */
void setup() {
  Arresta();
  int Distanza = 0;
  Serial.begin(115200);     // seriale utilizzata per il debug      
  Serial1.begin(115200);    // seriale utilizata per la trasmissione all'applicazione android
  potenza = Potenza_Minima;
  motore_posteriore_dx.setSpeed(potenza);
  motore_posteriore_sx.setSpeed(potenza);
  motore_anteriore_sx. setSpeed(potenza);
  motore_anteriore_dx. setSpeed(potenza);

  motore_posteriore_dx.run(RELEASE);
  motore_posteriore_sx.run(RELEASE);
  motore_anteriore_sx. run(RELEASE);
  motore_anteriore_dx. run(RELEASE);
 
  pinMode(pin_velocita, INPUT);
  digitalWrite(pin_velocita, HIGH);
  attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
  pulses = 0;

  pinMode(21, INPUT);
  digitalWrite(21, HIGH);
  attachInterrupt(digitalPinToInterrupt(21), Print_Info, FALLING);

  cm_al_secondo = 0;
  timeold = 0;
  timeold2 = 0;
  
  MyServo_Info.attach(9);
  MyServo_Info.write(90);
  
 
    MyServo.attach(10);
    MyServoWriteNew(20);
    MyServoWriteNew(160);
    MyServoWriteNew(90);
}

/* ---------- Loop Principale ---------- */
void loop() {
    
  bytericevuto = 0;
  if (Serial1.available() > 0) { bytericevuto = Serial1.read();   }
  else                         { delay(10);                       }
  
  Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
  if (Dist_Avanti < Distanza_Minima && (direzione == DIR_AVANTI)) {
   if (potenza > Potenza_Minima) {
    if (potenza > 200)      { potenza *= 0.50; }
    else if (potenza > 150) { potenza *= 0.65; }
    else                    { potenza *= 0.80; }
    Potenza(potenza);
    }
    if (Dist_Avanti <= 20) {
      Indietro();
      delay(20);
      Arresta(); 
      
    }      
  }
    
  if ( direzione == DIR_INDIETRO ) {
    Dist_Dietro = Misura_Distanza(SENSORE_INDIETRO);
    if (Dist_Dietro < Distanza_Minima) {
      if (potenza > 200)      { potenza *= 0.50; }
      else if (potenza > 150) { potenza *= 0.65; }
      else                    { potenza *= 0.80; }
      Potenza(potenza);
      }
    if (Dist_Dietro <= 20) {
      Avanti();
      delay(20);
      Arresta();
      Potenza(Potenza_Minima); 
    } 
  }
    
  switch (bytericevuto) {
    case ARRESTA:
      Arresta();
      break;
    case AVANTI:
      Avanti();
      break;
    case INDIETRO:
      Indietro(); 
      break;
    case DESTRA:
      Destra();
      break;
    case SINISTRA:
      Sinistra();
      break;
    case DESTRA_AVANTI:
      Destra_Avanti();
      break;
    case SINISTRA_AVANTI:
      Sinistra_Avanti();
      break;
    case DESTRA_INDIETRO:
      Destra_Indietro();
      break;
    case SINISTRA_INDIETRO:
      Sinistra_Indietro();
      break;
    case ACCELLERA:
      Accelera();
      break;
    case DECELERA:
      Decelera();
      break;
    case AUTOMATICO:
      Automatico();
      break;    
    case STOP:
      Arresta();
      Potenza(0);
      break;
    case POTENZA:
      while (Serial1.available() < 1 ){ delay(10); }
      potenza = Serial1.read();
      Potenza(potenza);
      break;
    case SETTING:
      Impostazioni();
       break;
    default:
      break;
   }        
}

/* ---------- Avanti ------------------- */
void Avanti(){
  if ( potenza < Potenza_Minima) {
    potenza = Potenza_Minima;
  }
  Potenza(potenza);
  motore_posteriore_dx.run(FORWARD);
  motore_posteriore_sx.run(FORWARD);
  motore_anteriore_sx. run(FORWARD);
  motore_anteriore_dx. run(FORWARD);
  direzione = DIR_AVANTI;
}

/* ---------- Indietro ----------------- */
void Indietro() {
  if ( potenza < Potenza_Minima) {
    potenza = Potenza_Minima;
  }
  Potenza(potenza);
  motore_posteriore_dx.run(BACKWARD);
  motore_posteriore_sx.run(BACKWARD);
  motore_anteriore_sx. run(BACKWARD);
  motore_anteriore_dx. run(BACKWARD);
  direzione = DIR_INDIETRO;
}

/* ---------- Arresta ------------------ */
void Arresta() {
  motore_posteriore_dx.run(RELEASE);
  motore_posteriore_sx.run(RELEASE);
  motore_anteriore_sx. run(RELEASE);
  motore_anteriore_dx. run(RELEASE);
  Potenza(potenza);
  direzione = DIR_STOP;
}

/* ---------- Potenza ------------------ */
void Potenza(int Speed) {  
  motore_posteriore_dx.setSpeed(Speed);
  motore_posteriore_sx.setSpeed(Speed);
  motore_anteriore_sx. setSpeed(Speed);
  motore_anteriore_dx. setSpeed(Speed); 
  potenza = Speed;
}

/* ---------- Destra ------------------- */
void Destra() {
  motore_posteriore_dx.run(BACKWARD);
  motore_posteriore_sx.run(FORWARD);
  motore_anteriore_sx. run(FORWARD);
  motore_anteriore_dx. run(BACKWARD); 
  direzione = DIR_DESTRA;
}

/* ---------- Sinistra ----------------- */
void Sinistra() {
  motore_posteriore_dx.run(FORWARD );
  motore_posteriore_sx.run(BACKWARD);
  motore_anteriore_sx. run(BACKWARD);
  motore_anteriore_dx. run(FORWARD );
  direzione = DIR_SINISTRA;  
}

/* ---------- Destra Avanti ------------ */
void Destra_Avanti() {
  motore_posteriore_dx.run(FORWARD);
  motore_posteriore_sx.run(FORWARD);
  motore_anteriore_sx. run(FORWARD);
  motore_anteriore_dx. run(FORWARD);
  motore_anteriore_dx. setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_posteriore_dx.setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_anteriore_sx. setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  motore_posteriore_sx.setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  direzione = DIR_AVANTI;
  }

/* ---------- Sinistra Avanti ---------- */
void Sinistra_Avanti() {
  motore_posteriore_dx.run(FORWARD);
  motore_posteriore_sx.run(FORWARD);
  motore_anteriore_sx. run(FORWARD);
  motore_anteriore_dx. run(FORWARD);
  motore_anteriore_sx. setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_posteriore_sx.setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_anteriore_dx. setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  motore_posteriore_dx.setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  direzione = DIR_AVANTI;
}

/* ---------- Destra Indietro ---------- */
void Destra_Indietro() {
  motore_posteriore_dx.run(BACKWARD);
  motore_posteriore_sx.run(BACKWARD);
  motore_anteriore_sx. run(BACKWARD);
  motore_anteriore_dx. run(BACKWARD);
  motore_anteriore_dx. setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_posteriore_dx.setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_anteriore_sx. setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  motore_posteriore_sx.setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  direzione = DIR_INDIETRO;
}

/* ---------- Sinistra Indietro -------- */
void Sinistra_Indietro() {
  motore_posteriore_dx.run(BACKWARD);
  motore_posteriore_sx.run(BACKWARD);
  motore_anteriore_sx. run(BACKWARD);
  motore_anteriore_dx. run(BACKWARD);
  motore_anteriore_sx. setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_posteriore_sx.setSpeed(potenza / RIDUZIONE_POTENZA_LOW);
  motore_anteriore_dx. setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  motore_posteriore_dx.setSpeed(potenza * RIDUZIONE_POTENZA_LOW);
  direzione = DIR_INDIETRO;
}
 

/* ---------- Accellera ---------------- */
void Accelera() { 
  potenza += Accelera_Decelera;
  if ( potenza > 250) {
    potenza = 250;
  }
  Potenza(potenza);
}
  
/* ---------- Decelera ----------------- */
void Decelera() { 
  potenza -= Accelera_Decelera;
  if ( potenza < 0) {
    potenza = 0;
  }
  Potenza(potenza);
}

/* ---------- Misura distanza ---------- */
int Misura_Distanza(int a_r) {
  int distanza_cm;
  distanza_cm = sonar[a_r].ping_cm();
  if ( distanza_cm <= 0 ) { 
    distanza_cm = MAX_DISTANCE;
  }
  return distanza_cm;
}

/* ---------- Impostazioni ---------- */
void Impostazioni() {
      while (Serial1.available() < 1 ){ delay(10); }
      Distanza_Frontale  = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      Distanza_Laterale  = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      Distanza_Minima    = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      Potenza_Automatico = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      Potenza_Minima     = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      Accelera_Decelera  = Serial1.read();
      while (Serial1.available() < 1 ){ delay(10); }
      offset             = (Serial1.read() - 90);
      while (Serial1.available() < 1 ){ delay(10); }
      Tempo_Rotazione    = (Serial1.read()*10);
      MyServoWriteNew(90);
  }


/* ---------- Avanzamento Automatico --- */
int Automatico() {
int returnvalue = 0;

  while (returnvalue != AUTOMATICO ) {
    Gradi = 0;
    if (Serial1.available() > 0){ returnvalue = Serial1.read();}
    Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
    while ( Dist_Avanti > Distanza_Frontale  && returnvalue != AUTOMATICO ){  
      if (Serial1.available() > 0){ returnvalue = Serial1.read();}
      // guarda a destra e sinistra
      if   (DestraSinistra) { Gradi++; }
      // guarda a sinistra
      else                  { Gradi--; }
      
      MyServo.write(90+Gradi+offset);
      if (abs(Gradi) > 25) { DestraSinistra = !DestraSinistra;}
      Avanti();
      Potenza(Potenza_Automatico);
      delay(10);        
      Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
    }
    Arresta();
    if (returnvalue == AUTOMATICO) {break;}
    Distanza_Ostacolo();
    // nel caso viene chiuso su tre lati va indietro
    if  ( Dist_Destra   < Distanza_Laterale && Dist_Destra_Diag   < Distanza_Frontale &&
          Dist_Sinistra < Distanza_Laterale && Dist_Sinistra_Diag < Distanza_Frontale &&
          Dist_Avanti   < Distanza_Frontale && (Dist_Dietro > 25)) { 
      DestraSinistra = false;
      Gradi = 0;
      while ( Dist_Avanti < Distanza_Frontale*2 ){  
        if (DestraSinistra){  Gradi += 2;  }
        else               {  Gradi -= 2;  }
        MyServoWriteNew(90+Gradi);
        if (abs(Gradi) > 70) {
          Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
          if (Dist_Avanti > Distanza_Laterale*2)  {
            Potenza(Potenza_Automatico*3);
            if ( Gradi > 0 ) { Sinistra();        }
            else             { Destra();          }  
            delay(Tempo_Rotazione); 
            break;
          }
          DestraSinistra = !DestraSinistra;
        }
        Potenza(Potenza_Minima);
        Indietro();
        delay(10);        
        Dist_Dietro = Misura_Distanza(SENSORE_INDIETRO);
        if (Dist_Dietro < 10) {  break;}
      }
      MyServoWriteNew(90);
      }
          
    // decide se girare a sinistra o destra
    else if  (Dist_Sinistra < Dist_Destra   && Dist_Sinistra < Dist_Avanti) {
        Potenza(Potenza_Automatico*3);
        Destra(); 
        delay(Tempo_Rotazione*0.75);
     }
    else if (Dist_Destra < Dist_Sinistra && Dist_Destra   < Dist_Avanti) {
      Potenza(Potenza_Automatico*3);
      Sinistra();
      delay(Tempo_Rotazione*0.75);
      }
    else if (Dist_Destra        < Distanza_Laterale)                     {
      Potenza(Potenza_Automatico*3);
      Sinistra();
      delay(Tempo_Rotazione);
      }
    else if (Dist_Sinistra      < Distanza_Laterale)                     {
      Potenza(Potenza_Automatico*3);
      Destra();
      delay(Tempo_Rotazione);
      } 
    else if (Dist_Sinistra_Diag < Distanza_Frontale)                     {
      Potenza(Potenza_Automatico*3);
      Destra();
      delay(Tempo_Rotazione);
      } 
    else if (Dist_Destra_Diag   < Distanza_Frontale)                     {
      Potenza(Potenza_Automatico*3);
      Sinistra();
      delay(Tempo_Rotazione);
      }
    else if (Dist_Destra>Dist_Sinistra && Dist_Destra>50)                {
      Potenza(Potenza_Automatico*3);
      Destra();
      delay(Tempo_Rotazione); }
    else if (Dist_Sinistra>Dist_Destra && Dist_Sinistra>50)              {
      Potenza(Potenza_Automatico*3);
      Sinistra();
      delay(Tempo_Rotazione); }
      
    else if (Dist_Avanti       <= Distanza_Frontale)                     {  
      DestraSinistra = false;
      Gradi = 0;
      while ( Dist_Avanti < Distanza_Frontale*2 ){  
        if (DestraSinistra){  Gradi += 2;  }
        else               {  Gradi -= 2;  }
        MyServoWriteNew(90+Gradi);
        if (abs(Gradi) > 70) {
          Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
          if (Dist_Avanti > Distanza_Laterale*2)  {
            Potenza(Potenza_Automatico*3);
            if ( Gradi > 0 ) { Sinistra();        }
            else             { Destra();          }  
            delay(Tempo_Rotazione); 
            break;
          }
          DestraSinistra = !DestraSinistra;
        }
        Potenza(Potenza_Minima);
        Indietro();
        delay(10);        
        Dist_Dietro = Misura_Distanza(SENSORE_INDIETRO);
        if (Dist_Dietro < 10) {  break;}
      }
      MyServoWriteNew(90);
    }
  }
  MyServoWriteNew(90);
  Arresta();
}

/* ---------- Distanza Ostacolo -------- */
void Distanza_Ostacolo()
{ 
  //Misura la distanza degli ostacoli, destra, sinistra, destra diagonale, sinistra diagonale, Avanti e dietro. 
  // Dist_Sinistra, Dist_Destra, Dist_Avanti; Dist_Dietro, Dist_Sinistra_Diag, Dist_Destra_Diag
  detachInterrupt(digitalPinToInterrupt(pin_velocita));
  detachInterrupt(digitalPinToInterrupt(21));
  Dist_Dietro = Misura_Distanza(SENSORE_INDIETRO);
  
  MyServoWriteNew(130);
  Dist_Sinistra_Diag = Misura_Distanza(SENSORE_AVANTI);
  
  MyServoWriteNew(170);
  Dist_Sinistra = Misura_Distanza(SENSORE_AVANTI);

  MyServoWriteNew(50);
  Dist_Destra_Diag = Misura_Distanza(SENSORE_AVANTI);
  
  MyServoWriteNew(10);
  Dist_Destra = Misura_Distanza(SENSORE_AVANTI);
  
  MyServoWriteNew(90);
  Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
  attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
  attachInterrupt(digitalPinToInterrupt(21), Print_Info, FALLING);
}

/* ---------- Stampa informazioni in APP -------- */
 void Print_Info() {
    if (millis() - timeold2 >= 500) {
      detachInterrupt(digitalPinToInterrupt(pin_velocita));
      detachInterrupt(digitalPinToInterrupt(21));
      cm_al_secondo = pulses*2/((millis() - timeold2)/500);
      pulses = 0; 
      timeold2 = millis();
      
      if (direzione != DIR_STOP && cm_al_secondo <= 5) {
        variabile += 1;
        if(variabile >= 10){
          variabile = 0;
          Arresta();
          
       }
      }
      else {variabile = 0;}
      attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
      attachInterrupt(digitalPinToInterrupt(21), Print_Info, FALLING);
    }
    if (millis() - timeold >= 100) {
       detachInterrupt(digitalPinToInterrupt(21));
       detachInterrupt(digitalPinToInterrupt(pin_velocita));
      if (direzione == DIR_INDIETRO) {
        cDistanza = String(Dist_Dietro);
      }     
       else  {
        cDistanza = String(Dist_Avanti);
      }
      
      while (cDistanza.length() < 3) {
        cDistanza = " " + cDistanza;
      }
      Serial1.print("D"+cDistanza);
      
      cPotenza = String( map(potenza, 0, 250, 0, 100));
      while (cPotenza.length() < 3 ) {
        cPotenza = " " + cPotenza;
      }     
      Serial1.print("P" + cPotenza);
      
      cVelocita = String(cm_al_secondo);
      while (cVelocita.length() < 3) {
        cVelocita = " " + cVelocita;
      }      
      Serial1.print("V" + cVelocita);
      
      timeold = millis();
      attachInterrupt(digitalPinToInterrupt(21), Print_Info, FALLING);
      attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
    }
 }


 /* ---------- Avanzamento Graduale Servo ------------------ */
void MyServoWriteNew(int Gradi) {  
  int oldposition = MyServo.read();
  if (oldposition > Gradi) {
    for (int i = oldposition; i > Gradi; i -=1) {
      MyServo.write(i+offset);
      delay(3);
    }
  } 
  else if (oldposition < Gradi) {
    for (int i = oldposition; i < Gradi; i +=1) {
      MyServo.write(i+offset);
      delay(3);
    }
  }
   MyServo.write(Gradi+offset);
}


  
Source for MIT APP INVENTOR 2Java
No preview (download only).
File APK for tabletJava
No preview (download only).
Arduino web editor

Schematics

car_control_GEGMIspxgm.jpg
Car control gegmispxgm
Car schematic
Car schematic f02ked9xvi

Comments

Similar projects you might like

Arduino Bluetooth Car Control

by TayfMavi

  • 4,925 views
  • 1 comment
  • 11 respects

Car Control with Arduino Uno and Bluetooth

Project tutorial by Mehmet SARI

  • 6,307 views
  • 11 comments
  • 39 respects

Arduino Robot w/ GoPro and FPV iPhone Control via Bluetooth

Project in progress by AlxArd

  • 3,902 views
  • 5 comments
  • 29 respects

Turn your RC Car to Bluetooth RC car

Project tutorial by Prajjwal Nag

  • 12,850 views
  • 2 comments
  • 15 respects

Bluetooth Controlled Car

Project in progress by samanfern

  • 8,845 views
  • 17 comments
  • 38 respects

Voice Control Bluetooth TV Remote

Project in progress by pravin.desai

  • 1,008 views
  • 0 comments
  • 4 respects
Add projectSign up / Login