Go Down

Topic: Robot autonomo con Arduino (Read 857 times) previous topic - next topic

simo96

Aug 04, 2013, 08:03 pm Last Edit: Aug 04, 2013, 08:21 pm by simo96 Reason: 1
Salve a tutti, è la prima volta che scrivo su questo forum. non è da molto tempo che mi diletto con arduino ma ultimamente ho avuto alcuni problemi con la programmazione del mio primo robot.
prima dell'ultima modifica il robot utilizzava solo due motoriduttori controllati con l293 e un sensore ad ultrasuoni hc-sr04. il robottino si muoveva e quando trovava un'ostacolo ad una certa distanza tornava indietro e provava a girare, provava..
Poi ho pensato, con l'utilizzo di un servomotore potrei semplificare di gran lunga le cose, facendo in modo che quando il robot è vicino all'ostacolo, si guarda intorno e trova "una via di fuga". Qui i problemi: non riesco a far leggere correttamente la distanza tramite il sensore ultrasuoni.

Questo è lo sketch ancora in fase di lavorazione:

Code: [Select]

#define ECHOPIN 6                            // Pin to receive echo pulse
#define TRIGPIN 7                            // Pin to send trigger pulse
int motor1_pin1 = 2;
int motor1_pin2 = 3;
int motor2_pin1 = 4;
int motor2_pin2 = 5;
int distance = 0;
int distanceleft = 0;
int distancefront = 0;
int distanceright = 0;
int pos = 0;
#include <Servo.h>
Servo myservo;  

void setup ()
{
 Serial.begin(9600);
 myservo.attach(9);
 pinMode(ECHOPIN, INPUT);
 pinMode(TRIGPIN, OUTPUT);
 pinMode(motor1_pin1,OUTPUT);
 pinMode(motor1_pin2,OUTPUT);
 pinMode(motor2_pin1,OUTPUT);
 pinMode(motor2_pin2,OUTPUT);

}
void ultrasuoni() {
 digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
 delayMicroseconds(2);
 digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
 delayMicroseconds(10);
 digitalWrite(TRIGPIN, LOW);                   // Send pin low again
 int distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
 distance= distance/58;    // Calculate distance from time of pulse
 if (distance <0 or distance >500) distance=0;
 return;
}

void loop()
{
 myservo.write(15);
 digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
 delayMicroseconds(2);
 digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
 delayMicroseconds(10);
 digitalWrite(TRIGPIN, LOW);                   // Send pin low again
 int distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
 distance= distance/58;    // Calculate distance from time of pulse
 if (distance <0 or distance >500) distance=0;
   
 distanceleft = distance;
 Serial.print(distanceleft);
 Serial.print("  ");
 delay(2000);
 
  myservo.write(90);
 digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
 delayMicroseconds(2);
 digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
 delayMicroseconds(10);
 digitalWrite(TRIGPIN, LOW);                   // Send pin low again
 distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
 distance= distance/58;    // Calculate distance from time of pulse
 if (distance <0 or distance >500) distance=0;
 
  distancefront = distance;
 Serial.print(distancefront);
 Serial.print("  ");
 delay(2000);
 
 myservo.write(165);
 digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
 delayMicroseconds(2);
 digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
 delayMicroseconds(10);
 digitalWrite(TRIGPIN, LOW);                   // Send pin low again
 distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
 distance= distance/58;    // Calculate distance from time of pulse
 if (distance <0 or distance >500) distance=0;
   
 distanceright = distance;
 Serial.print(distanceright);
 Serial.print("  ");
 delay(2000);
 
  }

Vorrei fare in modo di evitare di ripetere la parte di codice che fa funzionare il sensore ultrasuoni, ma ho avuto dei problemi nel farlo..
Attendo vostre notizie.

Simone

cyberhs

Hai creato la routine Ultrasuoni (il return finale è inutile), ma non la usi nel Loop!

P.S.: prima che Leo, il nostro moderatore, ti castri, inserisci il codice con l'apposito TAG "#"  :D

simo96

ho creato la routine ultrasuoni si, ma non la uso perchè usandola mi da le distanze "0" invece ripetendo funziona...

cyberhs

La funzione pulseIn restituisce il tempo in microsecondi: ti conviene usare una variabile long o meglio unsigned long al posto della int che arriva al massimo a 32767.

simo96

Ho cambiato un pò il funzionamento, anche dopo aver letto di altri robot online.
Ecco il nuovo sketch funzionante:
Code: [Select]

#include <Servo.h>
#define motor1_pin1 2
#define motor1_pin2 3
#define motor2_pin1 4
#define motor2_pin2 5
#define ECHOPIN 6                            // Pin to receive echo pulse
#define TRIGPIN 7                            // Pin to send trigger pulse
#define fariled 8
int distance = 0;
int distanceleft = 0;
int distanceright = 0;
int object= 35;


Servo myservo; 

void setup ()
{
  Serial.begin(9600);
  myservo.attach(9);
  pinMode(ECHOPIN, INPUT);
  pinMode(TRIGPIN, OUTPUT);
  pinMode(fariled, OUTPUT);
  pinMode(motor1_pin1,OUTPUT);
  pinMode(motor1_pin2,OUTPUT);
  pinMode(motor2_pin1,OUTPUT);
  pinMode(motor2_pin2,OUTPUT);

}

void loop()
{
  myservo.write(90);
  delay(200);
  digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
  delayMicroseconds(2);
  digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(TRIGPIN, LOW);                   // Send pin low again
  int distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
  distance= distance/58;    // Calculate distance from time of pulse
  if (distance <0 or distance >500) distance=0;
 
  if (distance > object) {
    avanti();
  }
  if (distance <= object) {
    trovastrada();
  }
}

void avanti() {
  digitalWrite(fariled,HIGH);
  digitalWrite(motor1_pin1,HIGH);
  digitalWrite(motor1_pin2,LOW);
  digitalWrite(motor2_pin1,HIGH);
  digitalWrite(motor2_pin2,LOW);
  digitalWrite(fariled,LOW);
  return;
}

void trovastrada() {
  fermati();
  retro();
  guardasinistra();
  guardadestra();
  if( distanceleft < distanceright)  {
    girasinistra();
  }
  else                               {
    giradestra();
  }
}
   
void retro() {
  digitalWrite(motor1_pin1,LOW);
  digitalWrite(motor1_pin2,HIGH);
  digitalWrite(motor2_pin1,LOW);
  digitalWrite(motor2_pin2,HIGH);
  delay(500);
  fermati();
  return;
}

void fermati() {
  digitalWrite(motor1_pin1,LOW);
  digitalWrite(motor1_pin2,LOW);
  digitalWrite(motor2_pin1,LOW);
  digitalWrite(motor2_pin2,LOW);
  delay(500);
  return;
}

void ultrasuoni() {
  digitalWrite(TRIGPIN, LOW);                   // Set the trigger pin to low for 2uS
  delayMicroseconds(2);
  digitalWrite(TRIGPIN, HIGH);                  // Send a 10uS high to trigger ranging
  delayMicroseconds(10);
  digitalWrite(TRIGPIN, LOW);                   // Send pin low again
  distance = pulseIn(ECHOPIN, HIGH);        // Read in times pulse
  distance= distance/58;    // Calculate distance from time of pulse
  if (distance <0 or distance >500) distance=0;
}

void guardasinistra(){
  myservo.write(30);
  delay(500);
  ultrasuoni();
  distanceleft = distance;
  Serial.print(distanceleft);
  Serial.print("  ");
  myservo.write(90);
  delay(500);
  return; 
}

void guardadestra(){
  myservo.write(150);
  delay(500);
  ultrasuoni();
  distanceright = distance;
  Serial.print(distanceright);
  Serial.print("  ");
  myservo.write(90);
  delay(500);
  return; 
 
}
void girasinistra() {
  digitalWrite(motor1_pin1,LOW);
  digitalWrite(motor1_pin2,HIGH);
  digitalWrite(motor2_pin1,HIGH);
  digitalWrite(motor2_pin2,LOW);
  delay(500);
  fermati();
  return;
}

void giradestra() {
  digitalWrite(motor1_pin1,HIGH);
  digitalWrite(motor1_pin2,LOW);
  digitalWrite(motor2_pin1,LOW);
  digitalWrite(motor2_pin2,HIGH);
  delay(500);
  fermati();
  return;
 
}


Se qualcuno ha altri suggerimenti, li accetterò voltentieri.

Simone

alexio

#5
Oct 20, 2013, 10:58 am Last Edit: Oct 20, 2013, 10:41 pm by alexio Reason: 1
perchè utilizzi return? il suo utilizzo in un metodo (funzione) void è descritta come opzionale, è possibile utilizzarla in quelle situazioni che ne cessitano l'uscita dalla funzione stessa.
essendo void <nomemetodo> () questa funzione non restituisce nessuna variabile.
l'istruzione return la puoi utilizzare ad esempio nella funzione ultrasuoni la quale non dovrà essere void ma bensì long; quindi
Code: [Select]

int triggerPort = 7;
int echoPort = 6;

long ultrasuoni(){
  digitalWrite(triggerPort, LOW);
 digitalWrite(triggerPort, HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPort, LOW);
 long durata = pulseIn (echoPort, HIGH);
 long distanza= 0.034*durata / 2;
 //delay(500);
 Serial.print( "durata: " );
 Serial.print( durata );
 Serial.print( " , " );
 Serial.print( "distanza: " );

 //dopo 38ms è fuori dalla portata del sensore
 if( durata > 38000 ) Serial.println( "fuori portata");
    else { Serial.print( distanza );
    Serial.println( "cm" );
  }
 return distanza;// l'istruzione return fornisce la variabile alla quale è assegnato la distanza in cm dall'ostacolo
}

simo96

Grazie per il consiglio, ma cosa cambia tra void <nomemetodo> () che non restituisce nessuna variabile
e  long <nomemetodo> () ??
ho notato che così è molto più preciso...
Grazie ancora.

alexio

il metodo void, se ci fai caso è il solito metodo utilizzato per definire il metodo setup e/o loop, questo tipo di metodo (funzione) esegue il codice e basta.
Se tu vuoi creare una funzione che ti restituisca un valore ad esempio funzione somma
Code: [Select]

int Somma(){
int a=5;
int b=6;
int S= a+b;
return s;
}
ma non è finita qua; potresti aver bisogno di inviare alla funzione dei valori da sottoporre alla funzione, torniamo alla funzione somma.
int  Somma(int a, int b){    //in questo caso nel richiamare la funzione sarà necessario passare anche i valori di a e b
int s = a + b;
return s;
}


la precisione che hai riscontrato è data dal fatto che è stata utilizzata una variabile long  che prende 4 byte ma ti permette di sfruttare valori che vanno da -2147483648 a 2147483647 e quindi un valore maggiore che non int ceh arriva a +/- 32768

simo96

ho sistemato un attimino lo sketch ed ecco come si presenta ora:
Code: [Select]
#define motor1_pin1 2
#define motor1_pin2 3
#define motor2_pin1 4
#define motor2_pin2 5
#define echopin 6                            // Pin to receive echo pulse
#define trigpin 7                            // Pin to send trigger pulse
int distance = 0;
int timepuls = 0;
int distanceleft = 0;
int distanceright = 0;
int object= 30;
#include <Servo.h>
Servo myservo;

void setup ()
{
 myservo.attach(8);
 pinMode(echopin, INPUT);
 pinMode(trigpin, OUTPUT);
 pinMode(motor1_pin1,OUTPUT);
 pinMode(motor1_pin2,OUTPUT);
 pinMode(motor2_pin1,OUTPUT);
 pinMode(motor2_pin2,OUTPUT);

}

void loop()
{
 myservo.write(90);
 delay(200);
 ultrasuoni();

 if (distance > object) {
   avanti();
 }
 if (distance <= object) {
   trovastrada();
 }
}

void avanti() {
 digitalWrite(motor1_pin1,HIGH);
 digitalWrite(motor1_pin2,LOW);
 digitalWrite(motor2_pin1,HIGH);
 digitalWrite(motor2_pin2,LOW);
 }

void trovastrada() {
 fermati();
 retro();
 guardasinistra();
 guardadestra();
 if( distanceleft < distanceright)  {
   girasinistra();
 }
 else                               {
   giradestra();
 }
}
 
void retro() {
 digitalWrite(motor1_pin1,LOW);
 digitalWrite(motor1_pin2,HIGH);
 digitalWrite(motor2_pin1,LOW);
 digitalWrite(motor2_pin2,HIGH);
 delay(500);
 fermati();
 return;
}

void fermati() {
 digitalWrite(motor1_pin1,LOW);
 digitalWrite(motor1_pin2,LOW);
 digitalWrite(motor2_pin1,LOW);
 digitalWrite(motor2_pin2,LOW);
 delay(500);
 return;
}

long ultrasuoni(){
 digitalWrite(trigpin, LOW);
 digitalWrite(trigpin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigpin, LOW);
 long timepuls = pulseIn (echopin, HIGH);
 long distance= 0.034*timepuls / 2;
 
 if (timepuls > 38000) distance=450;
return distance;
}


void guardasinistra(){
 myservo.write(30);
 delay(500);
 ultrasuoni();
 distanceleft = distance;
 myservo.write(90);
 delay(500);
 
}

void guardadestra(){
 myservo.write(150);
 delay(500);
 ultrasuoni();
 distanceright = distance;
 myservo.write(90);
 delay(500);
}

void girasinistra() {
 digitalWrite(motor1_pin1,LOW);
 digitalWrite(motor1_pin2,HIGH);
 digitalWrite(motor2_pin1,HIGH);
 digitalWrite(motor2_pin2,LOW);
 delay(500);
 fermati();  
}

void giradestra() {
 digitalWrite(motor1_pin1,HIGH);
 digitalWrite(motor1_pin2,LOW);
 digitalWrite(motor2_pin1,LOW);
 digitalWrite(motor2_pin2,HIGH);
 delay(500);
 fermati();  
}

Così è corretto?
Una cosa per vedere se ho capito bene,  il metodo void lancia le istruzioni contenute in esso, se uso invece long o int restituisce per forza un valore (sempre a seconda delle istruzioni date)?

alexio

#9
Oct 21, 2013, 07:54 pm Last Edit: Oct 21, 2013, 08:03 pm by alexio Reason: 1
Da una prima lettura veloce sembra prioprio di si.
esatto, ti ho proposto la funzione somma, per farti capire il funzionamneto.

una funzione somma con void potrebbe essere così :
Code: [Select]

void Somma(){
int a= 1;
int b=2;
int s=a+b; // esegue la somma
println(s); //stampa il risultato a video
}

ma in questo modo eseguiresti sempre la somma tra a e b cioè : 1+2
invece attraverso int, long, string, char, float, bolean e tanti altri tipi di variabli puoi inviare dei valori che saranno processati dalla funzione e ti sarà restituito un valore.

per fartela breve il compilatore deve sapere che tipo di dato verrà assegnato alla variabile che si è creata (inizializzata) perchè deve mettere a disposizione di quella variabile la parte di memoria necessaria.
Spero di avrti chiarito la differenza, comunque ti consiglio vivamente di acquistare o scaricare una guida di programmazione C ti sarà utile sempre, anche quando avrai una perfetta dimestichezza con la programmazione.
Le funzioni vengono utilizzate per eseguire delle parti di codice a piacimento quando è necessario e magari ripetutamente.

idrone

Mi permetto di aggiungere dei dettagli... (mi sto affacciando adesso alla programmazione di Arduino e a bazzicare per questo forum... per cui non conosco il codice di Arduino in se ma se non è molto differente da altri linguaggi di programmazione dovrebbe essere uguale)
nel creare una "funzione" hai diverse possibilità:

Code: [Select]

void Somma(){
int a= 1;
int b=2;
int s=a+b; // esegue la somma
println(s); //stampa il risultato a video
}

in questo caso crei una funzione che non ritorna alcun risultato con valori già prefissati.

Code: [Select]
void Somma(int a, int b){
int s=a+b; // esegue la somma
println(s); //stampa il risultato a video
}

in questo caso crei una funzione che non ritorna alcun risultato ma i valori glieli fornisci tramite il richiamo alla funzione
Code: [Select]
Somma(7, 3);

Code: [Select]

int Somma(){
int a= 1;
int b=2;
int s=a+b; // esegue la somma
return s;
}

In questo caso la funzione ti ritorna una variabile int utilizzabile nel tuo codice utilizzando però dei valori fissi
Code: [Select]
int miaSomma = Somma();

Code: [Select]
int Somma(int a, int b){
int s=a+b; // esegue la somma
return s;
}

In questo caso la funzione ti ritorna una variabile int utilizzabile nel tuo codice utilizzando i valori che gli passi nel richiamo alla funzione
Code: [Select]
int primaSomma = Somma(3,7);
int secondaSomma = Somma(2,5)


Come vedi se utilizzi una funzione void puoi stampare un valore a schermo o modificare un solo valore se invece utilizzi una funzione con ritorno puoi adattarla ad ogni variabile che necessiti...

Go Up