Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
DANNY003
Published © GPL3+

Bluetooth Controlled Car with Arduino Mega

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

IntermediateShowcase (no instructions)16,774
Bluetooth Controlled Car with Arduino Mega

Things used in this project

Hardware components

Arduino Mega 2560
Arduino Mega 2560
×1
Adafruit motor shield L293D
×1
HC-05 Bluetooth Module
HC-05 Bluetooth Module
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×2
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
Motor Encoder RPM Speed Counter Interrupter Sensor Module FC-03
×1
Convertitore DC-DC step-down LM317
×1
4WD-Robot-Smart-Car-Chassis-Kits-car-with-Speed-Encoder
×1
12 volt battery 1,3 ah
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Honeywell QMC5883L
×1
u-blox NEO-6M
×1

Software apps and online services

MIT App Inventor 2
MIT App Inventor 2

Story

Read more

Schematics

ELECTRICAL-DIAGRAM

CAR-SCHEMATIC-TOP

CAR-SCHEMATIC-BOTTOM

CAR-SCHEMATIC-INSIDE

Code

Arduino IDE

Arduino
#include <NMEAGPS.h>
#include <SoftwareWire.h>
#include <Servo.h>
#include <AFMotor.h>
#include <NewPing.h>
#define GPSport_h
#define gpsPort Serial3
#define GPS_PORT_NAME "Serial3"

SoftwareWire MyWire( 20, 21);
#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
#define OFFSET_GPS        96
#define OFFSET_BUSSOLA    97
#define CALIBRA_GPS       98
#define ATTIVA_GPS        99
#define GPS              100

#define PIN_PRINT_APP     18

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;
static NMEAGPS  gps; // This parses the GPS characters
static gps_fix  fix;
int direzione; 
int potenza;
int bytericevuto = 0;
String cPotenza;
String cDistanza;
String cVelocita;
int pin_velocita = 19;
unsigned int cm_al_secondo; 
volatile unsigned int pulses;
unsigned long timeold;  // controllo ogni 100mS per print info
unsigned long timeold1; // controllo ogni Secondo per l'avanzamento automatico GPS
unsigned long timeold2; // controllo ogni 500mS per il calcolo della velocit
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;
String dataingps       = "";
long latitudine_car =  0;
long longitudine_car = 0;
long latitudine_tablet = 0;
long longitudine_tablet = 0;
long distanza_tc = 0;
double angolo_tc = 0;
String cLatitudine = "";
String cLongitudine = "";
String cAngolo = "";
String cDistanza_tc = "";
int Angolo;
boolean Attivo_GPS = false;
int offset_bussola = 0;
long offset_lat = 0;
long offset_long = 0;
static double xlow  = 0;
static double ylow  = 0;
static double xhigh = 0;
static double yhigh = 0;

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

/* ---------- Setup -------------------- */
void setup() {
  MyWire.begin();
  QMC5883L_Configura();
  Arresta();
  int Distanza = 0;
  Serial.begin(115200);     // seriale utilizzata per il debug      
  Serial2.begin(115200);    // seriale utilizzata per la trasmissione all'applicazione android
  gpsPort.begin(115200);      // seriale utilizzata per il colloquio con GPS
  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);
  
  // interupt utilizzato per calcolare la velocit
  pinMode(pin_velocita, INPUT);
  digitalWrite(pin_velocita, HIGH);
  attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
  pulses = 0;
  
  // interupt utilizzato per inviare le informazioni all'APP sul tablet
  pinMode(PIN_PRINT_APP, INPUT);
  digitalWrite(PIN_PRINT_APP, HIGH);
  attachInterrupt(digitalPinToInterrupt(PIN_PRINT_APP), 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;
  int appoggio;
  if (Serial2.available() > 0) { bytericevuto = Serial2.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 (Serial2.available() < 1 ){ delay(10); }
      potenza = Serial2.read();
      Potenza(potenza);
      break;
    case SETTING:
      Impostazioni();
      break;
    case OFFSET_GPS:
      offset_lat  = (latitudine_car-latitudine_tablet);
      offset_long = (longitudine_car-longitudine_tablet);
      break;
    case OFFSET_BUSSOLA:
      offset_bussola = 0;
      offset_bussola = QMC5883L_Angolo();
      break;
    case CALIBRA_GPS:
      QMC5883L_Calibrazione();
      break;
    case ATTIVA_GPS:
      while (Serial2.available() < 1 ){ delay(10); }
      if (Serial2.peek() == 1 || Serial2.peek() == 2) {
         appoggio = Serial2.read();
         if      ( appoggio == 1) { Attivo_GPS = true ;  } 
         else if ( appoggio == 2) { Attivo_GPS = false ; } 
      }     
      break;    
    case GPS:
       Gps();
       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 (Serial2.available() < 1 ){ delay(10); }
      Distanza_Frontale  = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      Distanza_Laterale  = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      Distanza_Minima    = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      Potenza_Automatico = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      Potenza_Minima     = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      Accelera_Decelera  = Serial2.read();
      while (Serial2.available() < 1 ){ delay(10); }
      offset             = (Serial2.read() - 90);
      while (Serial2.available() < 1 ){ delay(10); }
      Tempo_Rotazione    = (Serial2.read()*10);
      MyServoWriteNew(90);
  }


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

  while (returnvalue != AUTOMATICO ) {
    Gradi = 0;
    if (Serial2.available() > 0){ returnvalue = Serial2.read();}
    Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
    while ( Dist_Avanti > Distanza_Frontale  && returnvalue != AUTOMATICO ){  
      if (Serial2.available() > 0){ returnvalue = Serial2.read();}
      // guarda a destra e sinistra
      if   (DestraSinistra) { Gradi++; }
      // guarda a sinistra
      else                  { Gradi--; }
      
      MyServo.write(90+Gradi+offset);
      if (abs(Gradi) > 30) { 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(PIN_PRINT_APP));
  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(PIN_PRINT_APP), Print_Info, FALLING);
}

/* ---------- Stampa informazioni in APP -------- */
 void Print_Info() {
    if (millis() - timeold2 >= 500) {
      detachInterrupt(digitalPinToInterrupt(pin_velocita));
      detachInterrupt(digitalPinToInterrupt(PIN_PRINT_APP));
      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;
          if (bytericevuto == 58) {Distanza_Ostacolo();}
          else {Arresta();}
       }
      }
      else {variabile = 0;}
      attachInterrupt(digitalPinToInterrupt(pin_velocita), counter, FALLING);
      attachInterrupt(digitalPinToInterrupt(PIN_PRINT_APP), Print_Info, FALLING);
    }
    if (millis() - timeold >= 100) {
       detachInterrupt(digitalPinToInterrupt(PIN_PRINT_APP));
       detachInterrupt(digitalPinToInterrupt(pin_velocita));
      if (direzione == DIR_INDIETRO) { cDistanza = String(Dist_Dietro);  }     
      else                           { cDistanza = String(Dist_Avanti);  }
      
      while (cDistanza.length() < 3) {  cDistanza = " " + cDistanza;     }
      Serial2.print("D"+cDistanza);
      
      cPotenza = String( map(potenza, 0, 250, 0, 100));
      while (cPotenza.length() < 3 ) {  cPotenza = " " + cPotenza;       }     
      Serial2.print("P" + cPotenza);
      
      cVelocita = String(cm_al_secondo);
      while (cVelocita.length() < 3) {  cVelocita = " " + cVelocita;     }      
      Serial2.print("V" + cVelocita);

      if ( Attivo_GPS ) {
         while (gps.available(gpsPort) ) {
           fix = gps.read(); // save the latest
           if (fix.valid.location) {
             latitudine_car = fix.latitudeL();
             longitudine_car = fix.longitudeL();   
           }      
         }
         String cAngolo_tc = String(angolo_tc,0);
         while (cAngolo_tc.length() < 3 ) {  cAngolo_tc = " " + cAngolo_tc; } 
         Serial2.print("C" + cAngolo_tc);
         
         //Angolo = QMC5883L_Angolo();
         cAngolo = String(Angolo);
         while (cAngolo.length() < 3 ) {  cAngolo = " " + cAngolo; } 
         Serial2.print("A" + cAngolo);
         
         cLatitudine = String(latitudine_car);
         while (cLatitudine.length() < 10) {  cLatitudine = " " + cLatitudine; } 
         Serial2.print("L" + cLatitudine);
      
         cLongitudine = String(longitudine_car);
         while (cLongitudine.length() < 10) {  cLongitudine = " " + cLongitudine; } 
         Serial2.print("G" + cLongitudine);

         cDistanza_tc = String(distanza_tc);
         while (cDistanza_tc.length() < 10 ) {  cDistanza_tc = " " + cDistanza_tc; } 
         Serial2.print("M" + cDistanza_tc);
      }
      timeold = millis();
      attachInterrupt(digitalPinToInterrupt(PIN_PRINT_APP), 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);
}


 /* ---------- Configura sensore QMC5883L  ------------------ */ 
 void  QMC5883L_Configura(){
   MyWire.beginTransmission(0x0D);
   MyWire.write(0x0B);
   MyWire.write(0x01);
   MyWire.endTransmission();  
   MyWire.beginTransmission(0x0D);
   MyWire.write(0x09);
   MyWire.write(0b11000000|0b00000000|0b00000100|0b00000001);
   MyWire.endTransmission();
 }

 /* ---------- Calibrazione sensore QMC5883L  ------------------ */ 
void QMC5883L_Calibrazione () {
  int returnvalue = 0;
  xlow = ylow = xhigh = yhigh = 0;
  unsigned long timeold = millis()+20000;
  Potenza(Potenza_Automatico*2);
    
  while ( (millis() < timeold ) && (returnvalue != ARRESTA ))  {    
       QMC5883L_Angolo(); 
       Destra();
       delay(40); 
       if (Serial2.available() > 0){ returnvalue = Serial2.read();} 
    }
    Arresta();
}

 /* ---------- Lettura sensore QMC5883L  ------------------ */ 
int QMC5883L_Angolo () {
  int nX,nY,nZ;
  float fx,fy;
  
  Arresta();
  delay(10);
  MyWire.beginTransmission(0x0D);
  MyWire.write(0x00);
  MyWire.endTransmission();
  MyWire.requestFrom(0x0D, 6);
  nX = MyWire.read() | (MyWire.read()<<8);
  nY = MyWire.read() | (MyWire.read()<<8);
  nZ = MyWire.read() | (MyWire.read()<<8);
  MyWire.endTransmission();
  
  if(nX<xlow)  xlow  += (nX - xlow )*0.2;
  if(nX>xhigh) xhigh += (nX - xhigh)*0.2;
  if(nY<ylow)  ylow  += (nY - ylow )*0.2;
  if(nY>yhigh) yhigh += (nY - yhigh)*0.2; 
 
  nX -= (xhigh+xlow)/2;
  nY -= (yhigh+ylow)/2;
  fx = (float)nX/(xhigh-xlow);
  fy = (float)nY/(yhigh-ylow);
 
  Angolo = (3.81667f + 180.0*atan2(fy,fx)/3.14159265358979323846264338327950288)-offset_bussola;
  if(Angolo<=0) Angolo += 360;
  if(Angolo>=360) Angolo -= 360;
  return Angolo;
}

/* ----------  GPS  ------------------ */ 

void Gps () {
  int returnvalue = 0;
  while (Serial2.available() < 1 ){ delay(10); }
  dataingps   = "" ;
  dataingps   = Serial2.readString();  
  latitudine_tablet  = (dataingps.substring(dataingps.indexOf("LAT")+3, dataingps.indexOf("LONG")).toInt())+offset_lat;
  longitudine_tablet = (dataingps.substring(dataingps.indexOf("LONG")+4, dataingps.length()).toInt())+offset_long;
  NeoGPS::Location_t tablet( latitudine_tablet, longitudine_tablet );
  NeoGPS::Location_t car   ( latitudine_car,    longitudine_car    );
  distanza_tc =  fix.location.DistanceKm      ( car, tablet );    
  angolo_tc   =  fix.location.BearingToDegrees( car, tablet );
  
  while (returnvalue != ARRESTA ) {
    if (Serial2.available() > 0){ returnvalue = Serial2.read();}
    Potenza(Potenza_Automatico*2);
    while (!(((Angolo+10)>=angolo_tc) && ((Angolo-10)<=angolo_tc)) && (returnvalue != ARRESTA) ) { 
      if (Serial2.available() > 0){ returnvalue = Serial2.read();}
      QMC5883L_Angolo();
      if(((Angolo-angolo_tc)<= 180) && ((Angolo-angolo_tc) >= 0)){Sinistra();}
      else {Destra();}
      delay(40);
    }
    if (distanza_tc<=1){
      Arresta();
      returnvalue = ARRESTA;
    }
    else {
      returnvalue=Automatico_GPS();
      if (distanza_tc<=1){
        Arresta();
        returnvalue = ARRESTA;
      }
    }
  }
}

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

    Gradi = 0;
    Potenza(Potenza_Automatico);
    Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
    while ( (Dist_Avanti > Distanza_Frontale)  && (returnvalue != ARRESTA) && (distanza_tc>1) ){  
      if (Serial2.available() > 0){ returnvalue = Serial2.read();}
      NeoGPS::Location_t tablet( latitudine_tablet, longitudine_tablet );
      NeoGPS::Location_t car   ( latitudine_car,    longitudine_car    );
      distanza_tc =  fix.location.DistanceKm      ( car, tablet );    
      angolo_tc   =  fix.location.BearingToDegrees( car, tablet );
      // guarda a destra e sinistra
      if   (DestraSinistra) { Gradi++; }
      // guarda a sinistra
      else                  { Gradi--; }
      
      MyServo.write(90+Gradi+offset);
      if (abs(Gradi) > 30) { DestraSinistra = !DestraSinistra;}
      Avanti();
      Potenza(Potenza_Automatico);
      delay(10);        
      Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
    }
    Arresta();
    if ((returnvalue != ARRESTA) && (distanza_tc>1)) {
      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;}
        }
     }
  motore_posteriore_dx.run(RELEASE);
  motore_posteriore_sx.run(RELEASE);
  motore_anteriore_sx. run(RELEASE);
  motore_anteriore_dx. run(RELEASE);
  Potenza(potenza);
  Distanza_Ostacolo();
  if (direzione == DIR_DESTRA){
    while(Dist_Sinistra < Distanza_Laterale*3){
      Potenza(Potenza_Automatico);
      Avanti();
      MyServoWriteNew(170);
      Dist_Sinistra = Misura_Distanza(SENSORE_AVANTI);
      if( Dist_Sinistra < Distanza_Laterale) {
        Potenza(Potenza_Automatico*3);
        Destra();
        delay(50);
        Arresta();
        }
      MyServoWriteNew(90);
      Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
      if (Dist_Avanti < Distanza_Frontale){
        Potenza(Potenza_Automatico*3);
        Destra(); 
        delay(Tempo_Rotazione*0.75);
        }
    }
    Potenza(Potenza_Automatico*3);
    Sinistra();
    delay(Tempo_Rotazione);
    Potenza(Potenza_Automatico);
    Avanti();
    delay(Tempo_Rotazione*2);
  }
  else if(direzione == DIR_SINISTRA){
    while(Dist_Destra < Distanza_Laterale*3){
      Potenza(Potenza_Automatico);
      Avanti();
      MyServoWriteNew(10);
      Dist_Destra = Misura_Distanza(SENSORE_AVANTI);
      if( Dist_Destra < Distanza_Laterale) {
        Potenza(Potenza_Automatico*3);
        Sinistra();
        delay(50);
        Arresta();
        }
      MyServoWriteNew(90);
      Dist_Avanti = Misura_Distanza(SENSORE_AVANTI);
      if (Dist_Avanti < Distanza_Frontale){
        Potenza(Potenza_Automatico*3);
        Sinistra(); 
        delay(Tempo_Rotazione*0.75);
        }
    } 
    Potenza(Potenza_Automatico*3);
    Destra();
    delay(Tempo_Rotazione);
    Potenza(Potenza_Automatico);
    Avanti();
    delay(Tempo_Rotazione*2);
    }
  
  }
  MyServoWriteNew(90);
  QMC5883L_Angolo();
  return returnvalue ; 
}

Source for MIT APP INVENTOR 2

Java
No preview (download only).

File APK for Tablet

Java
No preview (download only).

Arduino web editor

Credits

DANNY003
1 project • 23 followers

Comments