Auto smart con hc-sr04, l298n e Arduino uno R3

Ciao a tutti, nel mio progetto ho montato su un telaio 2 motori DC controllati da un driver l298n e alimentati da 4 batterie da 1,5 V l'una. Poi ho aggiunto 3 sensori ad ultrasuoni hc-sr04, uno davanti, uno a destra e uno a sinistra. Quando l'auto si avvia dovrebbe iniziare ad andare avanti in automatico, fermarsi se incontra un ostacolo a 20 cm, controllare lo spazio a destra e a sinistra e decidere da che parte andare. Il problema è che quando viene alimentata, la scheda si accende, ma non succede nulla.
Questo è il codice (non dà errori):

#include <NewPing.h>

// Pin motori
int N1 = 4; // Motore A avanti
int N2 = 6; // Motore A indietro
int N3 = 2; // Motore B avanti
int N4 = 7; // Motore B indietro
int ena1 = 3; // PWM Motore A
int ena2 = 5; // PWM Motore B

// Pin sensori ad ultrasuoni
#define echoRight 9
#define trigRight 8
#define trigLeft 11
#define echoLeft 10
#define trigFront 12
#define echoFront 13

#define maxDistance 20 

NewPing sonarFront(trigFront, echoFront, maxDistance);
NewPing sonarRight(trigRight, echoRight, maxDistance);
NewPing sonarLeft(trigLeft, echoLeft, maxDistance);

void setup() {
  pinMode(N1, OUTPUT);
  pinMode(N2, OUTPUT);
  pinMode(N3, OUTPUT);
  pinMode(N4, OUTPUT);
  pinMode(ena1, OUTPUT);
  pinMode(ena2, OUTPUT);
}

void loop() {
  int distanceFront = sonarFront.ping_cm();
  int distanceRight = sonarRight.ping_cm();
  int distanceLeft = sonarLeft.ping_cm();
 if (distanceFront > maxDistance) {
    moveForward();
 }else {
    stopMotors();
   if (distanceRight > maxDistance && distanceLeft <= maxDistance) {
      turnRight();
    } else if (distanceLeft > maxDistance && distanceRight <= maxDistance) {
      turnLeft();
    } else {
      stopMotors();
    }
  }
}

void moveForward() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, HIGH);
  digitalWrite(N3, LOW);
  digitalWrite(N4, HIGH);
  analogWrite(ena1, 225); 
  analogWrite(ena2, 225); 
}

void turnLeft() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, HIGH);
  digitalWrite(N3, HIGH);
  digitalWrite(N4, LOW);
  analogWrite(ena1, 0); 
  analogWrite(ena2, 225); 
  delay(500); 
  stopMotors();
}

void turnRight() {
  digitalWrite(N1, HIGH);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, HIGH);
  analogWrite(ena1, 225); 
  analogWrite(ena2, 0);
  delay(500); 
  stopMotors();
}

void stopMotors() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, LOW);
  analogWrite(ena1, 0);
  analogWrite(ena2, 0);
}

Grazie in anticipo.

Forse qua (non sono sicuro ma..):

NewPing sonarFront(trigFront, echoFront, maxDistance);

Limita la distanza massima al valore di maxDistance. Se è così,

if (distanceFront > maxDistance)

Non sarà mai true. E lo steso con gli altri distanze. Prova a chiamare il costruttore senza specifica di distanza massima o con valore maggiore di maxDistance.

Grazie mille, più tardi proverò

Ciao, scusate se scrivo dopo così tanto. Adesso la macchina va avanti solo se il sensore di destra rileva una distanza minore di 20cm e non si ferma contro gli ostacoli. Vi lascio il codice aggiornato:


#include <NewPing.h>

// Pin motori
int N1 = 4; // Motore A avanti
int N2 = 6; // Motore A indietro
int N3 = 2; // Motore B avanti
int N4 = 7; // Motore B indietro
int ena1 = 3; // PWM Motore A
int ena2 = 5; // PWM Motore B
// Pin sensori ad ultrasuoni
#define echoRight 9
#define trigRight 8
#define trigLeft 11
#define echoLeft 10
#define trigFront 12
#define echoFront 13

#define maxDistance 200// Distanza massima in cm
#define maxObstacleDistance 20// Distanza degli ostacoli massima in cm

NewPing sonarFront(trigFront, echoFront, maxDistance);
NewPing sonarRight(trigRight, echoRight, maxDistance);
NewPing sonarLeft(trigLeft, echoLeft, maxDistance);

void setup() {
  pinMode(N1, OUTPUT);
  pinMode(N2, OUTPUT);
  pinMode(N3, OUTPUT);
  pinMode(N4, OUTPUT);
  pinMode(ena1, OUTPUT);
  pinMode(ena2, OUTPUT);
 
}

void loop() {
  int distanceFront = sonarFront.ping_cm();
  int distanceRight = sonarRight.ping_cm();
  int distanceLeft = sonarLeft.ping_cm();
 if (distanceFront > maxObstacleDistance) {
    moveForward();
 }else {
    stopMotors();
   if (distanceRight > maxObstacleDistance && distanceLeft <= maxObstacleDistance) {
      turnRight();
    } else if (distanceLeft > maxObstacleDistance && distanceRight <= maxObstacleDistance) {
      turnLeft();
    } else {
      stopMotors();
    }
  }
}

void moveForward() {
  digitalWrite(N1, HIGH);
  digitalWrite(N2, HIGH);
  digitalWrite(N3, HIGH);
  digitalWrite(N4, HIGH);
  analogWrite(ena1, 255); // Velocità motore A
  analogWrite(ena2, 255); // Velocità motore B
}

void turnLeft() {
  digitalWrite(N1, HIGH);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, HIGH);
  analogWrite(ena1, 255); // Ferma motore A
  analogWrite(ena2, 0); // Velocità motore B
  delay(500); // Tempo di rotazione
  stopMotors();
}

void turnRight() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, HIGH);
  digitalWrite(N3, HIGH);
  digitalWrite(N4, LOW);
  analogWrite(ena1, 0); // Velocità motore A
  analogWrite(ena2, 255); // Ferma motore B
  delay(500); // Tempo di rotazione
  stopMotors();
}

void stopMotors() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, LOW);
  analogWrite(ena1, 0); // Velocità motore A
  analogWrite(ena2, 0); // Ferma motore B
  delay(500); // Tempo di rotazione
  
}


Grazie in anticipo

In "MoveForward" stai attivando tutto a HIGH, sia il "motore avanti" che il "motore indietro" per tutte due motori. Direi che dovresti mettere solo HIGH nelle due "motore avante" e in LOW le due "motore indietro".

Adesso sembra che vada, ma a scatti. Ho notato che quando il sensore di destra è ostruito, il led L si spegne e la macchina va avanti.

Rettifico, gira costantemente su se stessa verso destra a meno che il sensore non sia ostruito. In quel caso si ferma.

Invece che in termini di distanza assoluta dall'ostacolo, prova a ragionare su dove puoi andare oppure no.
Probabilmente ti semplifica la gestione dei movimenti.

Inoltre manca la condizione in cui tutti i sensori sono impegnati.
Ad esempio potresti fare una rotazione completa.

Secondo me si può evitare anche di arrestare il motore prima di girare calcolando bene i tempi.

In effetti questo semplifica molto la logica del programma, ma credo si aver sbagliato qualcosa nelle funzioni di rotazione e avanzamento, perché il problema persiste.

Separa il problema in singoli pezzi distinti e che puoi facilmente verificare/risolvere: ad esempio potresti implementare un semplice sketch per provare l'hardware dove usi il monitor seriale come input:

  • A, avanti per 1 secondo
  • D, rotazione a destra
  • S, rotazione a sinistra
  • I, indietro per 1 secondo

Quando sei certo che i movimenti siano correttamente eseguiti prosegui con la logica automatica.

Ho fatto come mi hai consigliato, ho creato un programmino che facesse andare la macchina avanti per un secondo e poi la fermasse. Il problema é che quando lo lancio il led L inizia a lampeggiare e non succede nulla. Forse è perché ora lo alimento con 9V ?

Metti il codice del programma di test cosi vediamo come lo hai implementato.

int N1 = 4; // Motore A avanti
int N2 = 6; // Motore A indietro
int N3 = 2; // Motore B avanti
int N4 = 7; // Motore B indietro
int ena1 = 3; // PWM Motore A
int ena2 = 5; // PWM Motore B
void setup() {
  // put your setup code here, to run once:
  pinMode(N1, OUTPUT);
  pinMode(N2, OUTPUT);
  pinMode(N3, OUTPUT);
  pinMode(N4, OUTPUT);
  pinMode(ena1, OUTPUT);
  pinMode(ena2, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
moveForward();
delay(1000);
stopMotors();
}
void moveForward() {
  digitalWrite(N1, HIGH);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, HIGH);
  analogWrite(ena1, 225); // Velocità motore A
  analogWrite(ena2, 225); // Velocità motore B
}
void stopMotors() {
  digitalWrite(N1, LOW);
  digitalWrite(N2, LOW);
  digitalWrite(N3, LOW);
  digitalWrite(N4, LOW);
  analogWrite(ena1, 0); // Ferma motore A 
  analogWrite(ena2, 0); // Ferma motore B
}

Controlla bene l'hardware ed i cablaggi: se definisci N1 e N3 per il movimento avanti, perché nella funzione attivi N1 ed N4?

I commenti sono importanti perché ti aiutano a mantenere il codice pulito e comprensibile, ma devono essere coerenti.

Tu stai usando un classico L298N che è essenzialmente un ponte ad H doppio.
Per far ruotare il motore da un lato devi azionare i transistor Q1 e Q4, mentre per invertire la direzione Q2 e Q3.

Per quanto riguarda l'alimentazione, se con 9V intendi una batteria "transistor" a forma di parallelepipedo, considera che quelle batterie possono erogare poche centinaia di mA e non hanno una gran durata.
Meglio le 4 stilo da 1.5V anche se i motori gireranno più piano.
A questo punto se fai uno schema anche del cablaggio abbiamo tutti gli elementi per valutare perché quando parli di led L che lampeggia, io non vedo alcun riferimento nello sketch.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.