Bluetooth 4WD Car

Salve gente eccomi di nuovo qui impelagato a chiedervi lumi :))
Come da titolo sto provando a realizzare una 4wd car con arduino allora le componenti sono:
arduino
L298N
modulo bluetooth hc-06
4 motorini dc

schema: Imgur: The magic of the Internet

Sketch

char t;
 
void setup() {
pinMode(13,OUTPUT);   //left motors forward
pinMode(12,OUTPUT);   //left motors reverse
pinMode(11,OUTPUT);   //right motors forward
pinMode(10,OUTPUT);   //right motors reverse
 
Serial.begin(9600);
 
}
 
void loop() {
if(Serial.available()){
  t = Serial.read();
  Serial.println(t);
}
 
if(t == '1'){            //move forward(all motors rotate in forward direction)
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
}
 
else if(t == '2'){      //move reverse (all motors rotate in reverse direction)
  digitalWrite(13,LOW);
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
}
 
else if(t == '3'){      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
}
 
else if(t == '4'){      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
}
 
else if(t == '5'){      //STOP (all motors stop)
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
}
delay(100);
}

Allora scusate il disegno dello schema ma è la prima volta che uso fritzing e non riuscivo a trovare il modulo L298N, il problema è che quando collego il cell tramite app android e lancio un comando (tipo avanzare) si sentono i motori partite per un secondo dopo di che si perde il collegamento bluetooth e non capisco perchè (ho provato diverse app tutte con lo stesso risultato), potete aiutarmi?? ty

Non sono un esperto di elettronica, ma potrebbe essere un problema di mancanza di corrente (pochi ampere). Quando si avviano i motori, questi assorbono tutta la corrente, il modulo BT non ne ha a sufficienza e si spegne.
Come alimenti il tutto ?

con un trasformatore a 12v stavo provando il tutto per vedere se andava

avevi ragione alimentando separatamente arduino e modulo Hc-06 il tutto funziona solo che i motori vanno veramente piano come potrei fare ad aumentare i giri dei motori??? servirebbe prendere un altro modulo L298N e gestirne 2 per modulo? oppure puoi indicarmi delle batterie adatte? i motori sono i classici dc https://www.amazon.it/XCSOURCE-motoriduttore-rotella-Projects-TE696/dp/B06XPCZ78W/ref=sr_1_2?ie=UTF8&qid=1514482434&sr=8-2&keywords=motori+arduino

Per questa domanda pazienta la risposta di qualcuno esperto di elettronica, sorry.

dai dati del motore e se non ho sbagliato i calcoli sembra che al massimo puoi avere una velocità di circa 3Kmh, :o A quanto alimenti l'L298? Visto che la tensione massima dei motori è di 6V. puoi alimentare l'L298 a 9V.

alimento l'L298 con un trasformatore 12v, 500ma credo che il problema siano i 500ma

non credo che i motori assorbono più di 500mA, per prova fai girare uno solo e vedi se gira più velocemente, mi sa che sono proprio quel tipo di motori che sono davvero piccoli e girano piano

Per avere un'idea della velocità massima di ciascun motore, prova ad alimentarlo direttamente con 6Vcc (4 batterie da 1,5V in serie). La corrente che assorbe ciascun motore è di 100-120mA, ampiamente entro le possibilità delle 4 batterie.

Come dice -zef- la velocità massima (con quelle gomme) è di circa 3 km/h. Sembra poco, ma sono 50 metri al minuto, oppure circa 83 cm al secondo!

Ciao,
P.

In realtà ho assemblato un cingolato come questo

ovviamente sulle ruote dentate ci stanno i cingoli ora oltre ad avere variazioni di andatura tra parte destra e sinistra (i motori di sinistra girano più velocemente e quindi il tank non va dritto) vanno relativamente piano e poi con il passare del tempo rallentano sempre più sino a non farcela più a spingere il tank.
Non capisco perchè man mano che sono in funzione per (pochi minuti) perdono potenza sino a non farcela più visto che sono alimentati dal L298n che è alimentato da un trasformatore a 12v, 500ma, collegato alla presa elettrica di casa (e non da una batteria che si potrebbe esaurire con il tempo).

avere due motori sullo stesso cingolo non mi sembra una buona idea, se un motore gira in modo diverso dall'altro causa un aumento di sforzo e quindi un consumo maggiore. Dopo che girano un po' e iniziano a perdere potenza hai notato se i motori, l'l298 o l'alimentatore scaldano parecchio?

tra le componenti ho notato che l'L298 è quello che scalda, ieri poi ho ripreso in mano il progetto per aggiungere un altro L'298 e mi sono accorto che tra il comando lanciato dal cellulare e la sua esecuzione ci sono tipo un paio di secondi di ritardo (cosa che fino all'altro giorno non succedeva) cosa può essere successo???

Una domanda sto provando a passare ad un controllo remoto IR e devo dire che il tank risponde bene (a parte il calo di potenza con il passare del tempo che devo ancora inquadrare) con questo codice

/* include library */
#include <IRremote.h>

/* define IR sensor pin */
int IRsensorPin = 12;

/* define the some functions used by the library */
IRrecv irrecv(IRsensorPin);
decode_results results;

/* define L298N motor drive control pins */
int RightMotorForward = 2;    // IN1
int RightMotorBackward = 3;   // IN2
int LeftMotorForward = 4;     // IN3
int LeftMotorBackward = 5;    // IN4


void setup(){
  
  /* initialize motor control pins as output */
  pinMode(LeftMotorForward,OUTPUT);
  pinMode(RightMotorForward,OUTPUT);
  pinMode(LeftMotorBackward,OUTPUT);
  pinMode(RightMotorBackward,OUTPUT);

  /* start serial communication to see hex codes */
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop(){
  
  /* if the sensor is receive any signal */
  if (irrecv.decode(&results))
  {
    
    /* print the hex code value on the serial monitor */
    Serial.println(results.value);
    delay(5);

    /* resume function according to hex code */
    irrecv.resume();
  }
  
  /* if the incoming data is "defined hex code" then run the motors functions */
  /* instead of zeros "0000", write the hex codes of your remote control */
  if(results.value == 0xFF18E7) MotorForward();
  if(results.value == 0xFF4AB5) MotorBackward();
  if(results.value == 0xFF10EF) TurnRight();
  if(results.value == 0xFF5AA5) TurnLeft();
  if(results.value == 0xFF38C7) MotorStop();
  
}

/* FORWARD */
void MotorForward(){
  digitalWrite(LeftMotorForward,HIGH);
  digitalWrite(RightMotorForward,HIGH);
  digitalWrite(LeftMotorBackward,LOW);
  digitalWrite(RightMotorBackward,LOW); 
}

/* BACKWARD */
void MotorBackward(){
  digitalWrite(LeftMotorBackward,HIGH);
  digitalWrite(RightMotorBackward,HIGH);
  digitalWrite(LeftMotorForward,LOW);
  digitalWrite(RightMotorForward,LOW);
}

/* TURN RIGHT */
void TurnRight(){
  digitalWrite(LeftMotorForward,HIGH); 
  digitalWrite(RightMotorForward,LOW);
  digitalWrite(LeftMotorBackward,LOW);
  digitalWrite(RightMotorBackward,HIGH);
}

/* TURN LEFT */
void TurnLeft(){
  digitalWrite(RightMotorForward,HIGH);  
  digitalWrite(LeftMotorForward,LOW);
  digitalWrite(LeftMotorBackward,HIGH);
  digitalWrite(RightMotorBackward,LOW);
}

/* STOP */
void MotorStop(){
  digitalWrite(LeftMotorBackward,LOW);
  digitalWrite(RightMotorBackward,LOW);
  digitalWrite(LeftMotorForward,LOW);
  digitalWrite(RightMotorForward,LOW);
}

Attualmente premendo il tasto e rilasciando il tank continua ad eseguire l'ultimo comando sino a quando non gli do il comando stop oppure un altro comando.
Volevo chiedervi modificando il codice è possibile fargli eseguire il comando finchè si tiene premuto l'apposito tasto ed interromperlo al rilascio??? (per intenderci come accadeva nell'app bluetooth)

Se tieni schiacciato un tasto di un telecomando a infrarossi viene trasmesso in continuazione un codice. Purtroppo spesso il PRIMO codice trasmesso alla pressione del tasto è DIVERSO dai codici trasmessi successivamente (che però dovrebbero essere tutti uguali).

A parte questo, per fare ciò che chiedi, potresti scrivere uno sketch molto semplice per misurare qual è il tempo di ripetizione del tuo telecomando. Sapendo poi che il tempo di ripetizione è (ad esempio) 200ms puoi impostare lo sketch del tank con un timeout di (sempre ad esempio) 250ms. Il timeout parte alla ricezione del primo codice e viene resettato tutte le volte che riceve un ulteriore codice. Se il timeout scatta (cioè mancata ricezione di un codice entro 250 ms) il comando cessa di essere eseguito.

C'è da tener presente la possibilità di perdita di una trasmissione di codice, o di trasmissione errata. Ciò farebbe cessare l'esecuzione del comando, che però verrebbe ripresa 200ms dopo alla ricezione del successivo codice valido.

Sta a te decidere se è più tollerabile che l'esecuzione del comando abbia un 'buco' di 200ms, oppure se non è meglio portare il timeout a 450ms 'coprendo' anche la perdita di un codice. Ciò però comporta un ritardo di circa mezzo secondo fra la cessata pressione del tasto del telecomando e l'effettiva cessazione dell'esecuzione del comando.

Ciao,
P.

Avendo problemi con la connessione IR (per la necessita di avere sempre la visuale del sensore ricevente) sono tornato al Bluetooth il tutto funziona solo che non riesco a capire perchè ho un ritardo di 2-3 secondi tra l'invio del comando tramite cell e l'esecuzione non riesco a comprendere il perchè?? potete aiutarmi???

char t;
 
void setup() {
pinMode(13,OUTPUT);   //left motors forward
pinMode(12,OUTPUT);   //left motors reverse
pinMode(11,OUTPUT);   //right motors forward
pinMode(10,OUTPUT);   //right motors reverse
 
Serial.begin(9600);
 
}
 
void loop() {
if(Serial.available()){
  t = Serial.read();
  Serial.println(t);
}
 
if(t == 'F'){            //move forward(all motors rotate in forward direction)
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
}
 
else if(t == 'B'){      //move reverse (all motors rotate in reverse direction)
  digitalWrite(13,LOW);
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
}
 
else if(t == 'R'){      //turn right (left side motors rotate in forward direction, right side motors doesn't rotate)
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
}
 
else if(t == 'L'){      //turn left (right side motors rotate in forward direction, left side motors doesn't rotate)
  digitalWrite(13,HIGH);
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
}
 
else if(t == 'S'){      //STOP (all motors stop)
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
}
delay(100);

non penso proprio che il problema sia del programma, a vederlo sembra ok, sarà qualche problema tra app/cell/bluetooth :confused:

Prova questa app è molto versatile

Arieccomi, risolto il problema dell modulo bluetooth volevo implementare la funzione di avanzamento automatico con rilevamento ostacoli attraverso un modulo Hc-04.
Ho provato ad implementare questo sketch

#include <Servo.h>

#define TRIG 4
#define ECHO 3

#define IN_11  7    // L298N #1 in 1 motor Right Ahead
#define IN_13  8    // L298N #1 in 3 motor Right Back
#define IN_21  9    // L298N #2 in 1 motor Left Ahead
#define IN_23  10    // L298N #2 in 3 motor Left Back

Servo servo;

int angle = 90;    
int lookLeft = 0; 
int lookRight = 0; 
int lookAhead = 0; 
int timeEcho;  

void setup() {  
   
   servo.attach(5);
  
     pinMode(TRIG, OUTPUT); 
     pinMode(ECHO, INPUT); 
  
     pinMode(IN_11, OUTPUT);
     pinMode(IN_13, OUTPUT);
     pinMode(IN_21, OUTPUT);
     pinMode(IN_23, OUTPUT);
    
  } 


void goAhead(){ 

        digitalWrite(IN_11, HIGH);
        digitalWrite(IN_13, LOW);
        digitalWrite(IN_21, HIGH);
        digitalWrite(IN_23, LOW);
  
  }

void goBack(){ 

        digitalWrite(IN_11, LOW);
        digitalWrite(IN_13, HIGH);
        digitalWrite(IN_21, LOW);
        digitalWrite(IN_23, HIGH);
  }

void goRight(){ 

        digitalWrite(IN_11, HIGH);
        digitalWrite(IN_13, HIGH);
        digitalWrite(IN_21, LOW);
        digitalWrite(IN_23, LOW);

  }

void goLeft(){

        digitalWrite(IN_11, LOW);
        digitalWrite(IN_13, LOW);      
        digitalWrite(IN_21, HIGH);
        digitalWrite(IN_23, HIGH);
        
  }


void stopRobot(){  

        digitalWrite(IN_11, LOW);
        digitalWrite(IN_13, LOW);
        digitalWrite(IN_21, LOW);
        digitalWrite(IN_23, LOW);
  
  }

void distanceLeft(){     
  
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  timeEcho = pulseIn(ECHO, HIGH);
  lookLeft = timeEcho/58;

  }

void distanceAhead(){     
  
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
    timeEcho = pulseIn(ECHO, HIGH);
  lookAhead = timeEcho/58;

  }

void distanceRight(){        
    
  digitalWrite(TRIG, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG, LOW);
    timeEcho = pulseIn(ECHO, HIGH);
    lookRight = timeEcho/58;
  
  }


void loop(){
  
  distanceAhead();
      if(lookAhead<30){
          stopRobot();
          delay(1000);  
          goBack();
          delay(200); 
          stopRobot();
          delay(1000);    
          for(angle=90;angle>=10;angle--){
              servo.write(angle);
              delay(5);
            }
    
      distanceRight();
    delay(100);
      for(angle=10;angle<=170;angle++){
          servo.write(angle);
          delay(5);
        }

    distanceLeft();
    delay(100);
        for(angle=170;angle>=90;angle--){
            servo.write(angle);
            delay(5);
          }
  
    if(lookLeft < lookRight){
    
          goRight();
          delay(250);
          stopRobot();
        }
  
      else{

          goLeft();
          delay(250);
        stopRobot();
        }
       
          }
  
    else{
      goAhead();
      }
  }

Solo che attualmente ciò che fa è avanzare, fermarsi, guardare a destra e sinistra, avanzare, fermarsi ....e ripete ciò all'infinito indipendentemente se ha davanti un ostacolo o meno.
Mentre ciò che vorrei che facesse sarebbe avanzare finchè non trova un ostacolo, indietreggiare un pochino guaradre a destra e sinistra e girare dove non vi è l'ostacolo per poi avanzare.
Qualcuno potrebbe aiutarmi a capire dove sbaglio

Il codice indentalo meglio, usa CTRL+T dentro a IDE. Scritto così non si capisce dove sono i blocchi delle graffe.

Indentato meglio la loop vedi che alla fine fa questo:

void loop() {
  distanceAhead();    // legge distanza
  if (lookAhead < 30) 
  { // un fracco di roba
  }
  else {
    goAhead();
  }
}

Non sò dove lo hai copiato, ma pare faccia semplicemente una verifica della distanza, se NON minore di 30 esegue goAHead() mentre se sotto 30 allora fa un casino di roba.
Siccome goAHead() mette semplicemente il motore avanti, se fa altre cose allora è entrato in quell'if e perciò rileva <30 più spesso di quello che ti aspetti.

Sinceramente ne ho provati un sacco scaricati da vari tutorial ma non ce n'è uno che funziona, (io mastico da poco arduino e finchè si tratta di cose singole ok ma quando intervengono più variabili mi perdo un pò), cmq ora l'ho un pò corretto e formattato

#include <Servo.h>

#define TRIG 3
#define ECHO 2

#define IN_11  7    // L298N #1 in 1 motor Right Ahead
#define IN_13  8    // L298N #1 in 3 motor Right Back
#define IN_21  9    // L298N #2 in 1 motor Left Ahead
#define IN_23  10   // L298N #2 in 3 motor Left Back

Servo servo;

int angle = 90;
int lookLeft = 0;
int lookRight = 0;
int lookAhead = 0;
int timeEcho;

void setup() {

  servo.attach(5);

  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);

  pinMode(IN_11, OUTPUT);
  pinMode(IN_13, OUTPUT);
  pinMode(IN_21, OUTPUT);
  pinMode(IN_23, OUTPUT);

}


void goAhead() {

  digitalWrite(IN_11, LOW);
  digitalWrite(IN_13, HIGH);
  digitalWrite(IN_21, LOW);
  digitalWrite(IN_23, HIGH);

}

void goBack() {

  digitalWrite(IN_11, HIGH);
  digitalWrite(IN_13, LOW);
  digitalWrite(IN_21, HIGH);
  digitalWrite(IN_23, LOW);
}

void goRight() {

  digitalWrite(IN_11, HIGH);
  digitalWrite(IN_13, HIGH);
  digitalWrite(IN_21, LOW);
  digitalWrite(IN_23, LOW);

}

void goLeft() {

  digitalWrite(IN_11, LOW);
  digitalWrite(IN_13, LOW);
  digitalWrite(IN_21, HIGH);
  digitalWrite(IN_23, HIGH);

}


void stopRobot() {

  digitalWrite(IN_11, LOW);
  digitalWrite(IN_13, LOW);
  digitalWrite(IN_21, LOW);
  digitalWrite(IN_23, LOW);

}

void distanceLeft() {

  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  timeEcho = pulseIn(ECHO, HIGH);
  lookLeft = timeEcho / 58;

}

void distanceAhead() {

  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  timeEcho = pulseIn(ECHO, HIGH);
  lookAhead = timeEcho / 58;

}

void distanceRight() {

  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  timeEcho = pulseIn(ECHO, HIGH);
  lookRight = timeEcho / 58;

}


void loop() {

  distanceAhead();
  if (lookAhead < 30) {
    stopRobot();
    delay(1000);
    goBack();
    delay(200);
    stopRobot();
    delay(1000);
    for (angle = 90; angle >= 10; angle--) {
      servo.write(angle);
      delay(5);
    }

    distanceRight();
    delay(100);
    for (angle = 10; angle <= 170; angle++) {
      servo.write(angle);
      delay(5);
    }

    distanceLeft();
    delay(100);
    for (angle = 170; angle >= 90; angle--) {
      servo.write(angle);
      delay(5);
    }

    if (lookLeft < lookRight) {

      goRight();
      delay(250);
      stopRobot();
    }

    else {

      goLeft();
      delay(250);
      stopRobot();
    }

  }

  else {
    goAhead();
  }
}

Come dici te va avanti se trova un ostacolo (<30) si ferma torna un pò indietro, poi riparte e si riferma perchè non gira, la parte che non riesco ad implementare e fargli valutare se ha più spazio a destra o a sinistra e farlo girare in quella direzione

Quando entri nel <30 chi ha scritto quel codice fa tutta quella serie di cose.
E' tutto spezzato in blocchi/funzioni logiche e non mi pare male.

Devi capire quello che fa quando entra nel <30 e capire con quali funzioni fa i vari passi che ottieni ora.
Esempio: la prima cosa stoppa con stopRobot(); attende un secondo (chissà perchè!!) e poi va indietro per 0,2 secondi con goBack(); e delay(200); e via dicendo.
Cambiando la sequenza di quei passi dovresti riuscire a fargli fare i passi che tu vuoi.

Chiamando ad esempio la distanceLeft(); subito dopo avrai in lookLeft la distanza a sinistra e con distanceRight(); in lookRight la distanza a destra.
Naturalmente prima devi fargli girare la testa a sx e dx e presumo siano quei for() con servo.write