Indice

Progetto finale: un robot esploratore

Vogliamo realizzare un robot esploratore capace di muoversi autonomamente ed evitare gli ostacoli cambiando direzione quando ne incontra uno. Per rilevare gli ostacoli useremo un sensore a ultrasuoni; per muovere il robot due motori pilotati dalla scheda Arduino con il motor shield Arduino.

vista inferiore del telaio: motori, riduttori, ruote e cavi di alimentazione

La struttura del robot è costituita da un telaio in plastica che supporta:

Il risultato finale è questo:

Progetto: un robot esploratore

Scopo realizzare un robot esploratore che evita gli ostacoli
Componenti telaio con ruote motori e riduttori, arduino motor shield, 4batterie stilo da 1,5 Volt, sensore a ultrasuoni HC-SR04

Approfondimento sull'hardware : il motor shield Arduino

Arduino Motor Shield R3

Il Motor Shield Arduino si monta sopra la scheda Arduino e permette di collegare un motore alla scheda. Il componente principale dello shield è l'integrato L298 che contiene due ponti H con i quali comandare due motori in continua o un motore passo-passo. Si possono collegare motori da 5 a 12 Volt che assorbono una corrente fino a 2 Ampère. Per alimentare la scheda, lo shield e i due motori useremo quattro batterie stilo per un totale di 6 Volt.

Lo shield utilizza 8 pin della scheda Arduino; noi ne useremo quattro, in particolare:

funzione pin (motore A) pin (motore B)
direzione (avanti/indietro) 12 13
velocità (tensione al motore) 311

NB lo shield usa anche i pin A0 e A1 per misurare le correnti e i pin 8 e 9 per l'arresto rapido dei motori; se si vuole utilizzare ad altro scopo questi pin occorre tagliare i rispettivi collegamenti sul retro dello shield1).

Comandare due motori in continua è molto semplice:

Approfondimento sull'hardware : il motore in continua

In questo progetto utilizzeremo due motori in continua per muovere il robot. Le due ruote devono muoversi in maniera indipendente - avanti e indietro e con velocità diverse - per far cambiare direzione al robot.

motore in continua, fonte sparkfun.com

Le caratteristiche principali dei motori in continua sono:

Il motore si aziona applicando tensione e la sua velocità è proporzionale al valore di tensione applicato. Per invertire la direzione è sufficiente invertire la tensione.

Il movimento del motore viene trasmesso al carico - in questo caso le ruote - attraverso l'albero. Più precisamente viene trasmessa una potenza meccanica che corrisponde al prodotto tra la velocità di rotazione e la coppia (la “spinta” o meglio l'equivalente della forza dei moti rettilinei):

`P=C cdot omega`

dove P è la potenza in Watt (W), C la coppia in newton per metro (Nm) e ω la velocità in radianti al secondo (rad/s)2).

Nel nostro caso non è possibile collegare direttamente le ruote all'albero perché i motori sono costruiti per girare molto velocemente - ad esempio a 1000 giri al minuto (rpm) - e le ruote girerebbero troppo velocemente. Per questo i motori montati sul telaio sono equipaggiati con un riduttore, un sistema ad ingranaggi che trasmette potenza meccanica riducendo la veocità, più o meno come il cambio di un'automobile o di una bicicletta.

I due motoriduttori (motore più riduttore) montati sul telaio hanno queste caratteristiche:

tensione massima 4,5 Volt in continua
velocità massima senza carico 10 rpm
corrente senza carico 190 mA
corrente massima 250 mA

sketch

/*
 * Progetto Finale: un robot esploratore che evita gli ostacoli
 * Il robot si muove autonomamente: procede con una traiettoria 
 * rettilinea finché non incontra un ostacolo (rilevato con un
 * sensore a ultrasuoni), quindi cambia direzione
 *
 * Nome Studente:
 * Creato il: data
 */
 
// pin collegati a trigger ed echo del sensore a ultrasuoni
int pinTrig = 4;
int pinEcho = 5;
// durata dell'impulso echo in microsecondi 
unsigned long durata;
// distanza dell'ostacolo in centimetri
int distanza;
// timeout della funzione pulseIn() in assenza di impulso echo
unsigned long timeout = 100000;
// pin direzione e velocità del motore sinistro
int pinDirS = 13;
int pinVelS = 11;
// pin direzione e velocità del motore destro
int pinDirD = 12;
int pinVelD = 3;
 
void setup(){
  // imposto i pin del sensore
  pinMode(pinTrig, OUTPUT);
  pinMode(pinEcho, INPUT);
  // imposto i pin del motore sinistro
  pinMode(pinDirS, OUTPUT);
  pinMode(pinVelS, OUTPUT);
  // imposto i pin del motore destro
  pinMode(pinDirD, OUTPUT);
  pinMode(pinVelD, OUTPUT);
}
 
void loop(){
  // RILEVAMENTO OSTACOLO
 
  // impulso di 10us dalla scheda al pin trigger del sensore
  digitalWrite(pinTrig, HIGH); 
  delayMicroseconds(10); 
  digitalWrite(pinTrig, LOW); 
  // calcolo la durata dell'impulso echo inviato dal sensore 
  durata = pulseIn(pinEcho, HIGH, timeout); 
  // converto la durata dell'impulso in distanza in centimetri 
  distanza = durata / 58; 
 
  // MARCIA DEL ROBOT
 
  // cambia direzione se l'ostacolo è a meno di 15 centimetri
  // (distanza 0 significa nessun ostacolo)
  if(distanza != 0 && distanza < 15){
    // va indietro a sinistra per un secondo
    digitalWrite(pinDirS, LOW);
    digitalWrite(pinDirD, LOW);
    analogWrite(pinVelS, 255);
    analogWrite(pinVelD, 100);
    delay(1000);
  }
  // altrimenti va dritto
  else {
    digitalWrite(pinDirS, HIGH);
    digitalWrite(pinDirD, HIGH);
    analogWrite(pinVelS, 255);
    analogWrite(pinVelD, 255);
  }
 
  // breve ritardo tra una misura e l'altra
  delay(100); 
}

Osservazioni

Torna all'indice.

1)
nel nostro caso i pin per la frenatura non sono utilizzati nel programma e risultano scollegati (di default i pin sono impostati come ingressi ad alta impedenza); nello shield invece una resistenza di pull-down disabilita l'arresto rapido
2)
spesso la velocità è espressa in giri al minuto (rpm) anche se non è l'unità di misura prevista dal Sistema Internazionale