Project showcase
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.
- 14,194 views
- 14 comments
- 27 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) Gps mode, 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.
Screenshot APK:
Code
#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 ;
}
Arduino web editor
Schematics
Comments
Author
Published on
February 23, 2019Members who respect this project
you might like