Come primo progetto per scoprire la potenza e la semplicità di Arduino ho deciso di costruire un piccolo robot in grado di muoversi ed evitare gli ostacoli in completa autonomia.
Fin dalle scuole superiori sono stato affascinato dal mondo dell’elettronica ed inoltre la mia passione (e anche mestiere) è programmare, sono riuscito a combinare entrambe le cose in questo progetto.
Come prima cosa mi sembra giusto dire che per sviluppare questo robot sono necessari un minimo di conoscenze di elettronica, nonchè un pò di manualità ed ingegno per risolvere i vari problemi che si possano presentare.
Volendo descrivere brevemente il mio progetto sono presenti quattro componenti principali:
- Arduino, il cervello del sistema
- il motore che fa muovere il robot e il motor driver per controllare il motore (verso e velocità)
- lo sterzo e il servo comando per cambiare direzione
- sensore di prossimità, per rilevare gli ostacoli
Elenco componenti e prezzi
Componente | Qta | Costo EUR (approx) |
Arduino Uno | 1 | 20,00 |
Hitec HS-422 | 1 | 9,00 |
SRF05 – Ultra-Sonic Ranger | 1 | 23,00 |
Tamiya Twin Motor Gearbox (70097) | 1 | 15,00 |
Tamiya Truck Tire Set | 1 | 6,00 |
SN754410NE Motor driver | 1 | 3,80 |
L7806 (regolatore tensione 6V) | 1 | 0,50 |
LM1117 (regolatore tensione 3.3V) | 1 | 1,50 |
Condensatore 100µF | 1 | – |
Condensatore 10µF | 1 | – |
Condensatore 0.33µF | 1 | – |
Condensatore 0.1µF | 1 | – |
Breadboard | 1 | 5,00 |
Connettore coassiale 2,1 mm | 1 | 1,00 |
TOTALE | – | 78,80 |
Altro materiale necessario:
- mattoncini Lego Technic
- cavi di varie lunghezze e colori
- batteria (consiglio una Ni-MH da 8,4V oppure una Li-Po 2S 7,4V)
Costruzione del prototipo
L’immagine seguente rappresenta lo schema elettrico del sistema:
Per chi ancora non lo conoscesse, per disegnarlo ho utilizzato Fritzing (http://fritzing.org), un software open source sviluppato per la progettazione elettronica.
Alcune note tecniche sul circuito:
- entrambi i regolatori di tensione hanno bisogno di condensatori per smorzare i possibili sbalzi di corrente (come indicato nei relativi datasheet)
- il gearbox utilizzato contiene due motori indipendenti, e ognuno è collegato ad un canale diverso del SN754410 in maniera da non sovraccaricare il circuito integrato. Ho collegato i pin di enable e input dei due canali assieme, in modo da far operare i due motori in parallelo.
- il sensore SRF05 ha due modalità di funzionamento: pin separati per trigger ed echo oppure un unico pin per entrambi. Ho utilizzato la seconda modalità per utilizzare meno pin su Arduino.
Ho scelto di utilizzare i mattoncini Lego Technic perché ne possiedo in quantità industriale e sono molto versatili. Alla fine della costruzione però ho notato che rendono il robot più pesante di quanto mi sarei aspettato, comunque ritengo sia una valida scelta.
La prima pietra è stata la costruzione del telaio attorno al gearbox dei motori ed il posizionamento di Arduino.
Il secondo passo (nonché uno dei più complicati per me) è stata la costruzione dello sterzo con i pezzi che avevo a disposizione e l’innesto del servo comando con gli ingranaggi Lego. Il risultato non è stato dei migliori perché lo sterzo ha molto gioco, ma fortunatamente sono riuscito a correggere il difetto tarando via software il servo.
Successivamente ho collocato il sensore di distanza SRF05 sul fronte del robot.
Il quarto ed ultimo passo, per quanto riguarda la meccanica, è stato il posizionamento della breadboard e della batteria in cima al telaio.
Infine alcune foto di dettaglio del circuito assemblato sulla breadboard.
Codice sorgente
Di seguito il codice che permette il funzionamento del robot.
#include <Servo.h> Servo myservo; // create servo object to control a servo const int servoPin = 4; const int motor1Pin = 7; // H-bridge leg 1 (pin 2, 1A) const int motor2Pin = 8; // H-bridge leg 2 (pin 7, 2A) const int enablePin = 11; // H-bridge enable pin const int signalPin = 12; // pin Arduino a cui è collegato il sensore SRF05 // distanza dell'oggetto int distance = 0; const int numOfReadings = 3; // number of readings to take/ items in the array int readings[numOfReadings]; // stores the distance readings in an array int arrayIndex = 0; // arrayIndex of the current item in the array int total = 0; // stores the cumlative total int avgDistance = 0; // stores the average value int sogliaStop; int sogliaSter; int sogliaRall; boolean isAvanti; int randNumber; int tmp; void setup() { Serial.begin(9600); // open serial port to receive data myservo.attach(servoPin); // attaches the servo on pin 9 to the servo object pinMode(motor1Pin, OUTPUT); pinMode(motor2Pin, OUTPUT); pinMode(enablePin, OUTPUT); // spengo i motori digitalWrite(enablePin, LOW); randomSeed(analogRead(0)); randNumber = 0; isAvanti = true; sogliaStop = 10; // soglia di stop / retromarcia sogliaSter = 40; // distanza a cui muovere lo sterzo sogliaRall = 50; // distanza a cui moderare la velocità // create array loop to iterate over every item in the array for (int thisReading = 0; thisReading < numOfReadings; thisReading++) { readings[thisReading] = 0; } // metto lo sterzo in posizione centrale myservo.write(0); delay(100); raddrizza(); } void loop() { distance = getDistance(); total = total - readings[arrayIndex]; // subtract the last distance readings[arrayIndex] = distance; // add distance reading to array total = total + readings[arrayIndex]; // add the reading to the total arrayIndex++; // go to the next item in the array // At the end of the array then start again if (arrayIndex >= numOfReadings){ arrayIndex = 0; } avgDistance = total / numOfReadings; // calculate the average distance Serial.print("MEDIA: "); Serial.println(avgDistance); if(isAvanti) { if(avgDistance<=sogliaStop) { // retromarcia al 100% raddrizza(); indietro(100); } else if(avgDistance<=sogliaRall) { // regola la velocità in base alla distanza dell'ostacolo tmp = map(avgDistance, sogliaStop, sogliaRall, 0, 100); avanti(tmp); // se la distanza è inferiore ad una soglia, sterza a dx o sx in maniera casuale if(avgDistance<=sogliaSter) { if(randNumber==0) randNumber = random(1,100); if(randNumber%2) { // destra myservo.write(180); // sinistra //myservo.write(0); } else { // destra myservo.write(180); // sinistra //myservo.write(0); } } } else { raddrizza(); avanti(100); } } else { // se sta andando in retromarcia, continua finchè l'ostacolo non è a debita distanza if(avgDistance<=sogliaRall) { indietro(100); } else { avanti(100); } } // attende 100 millisecondi prima di incominciare una nuova misura delay(100); } long getDistance() { // durata dell'impulso unsigned long pulseTime; unsigned long distance; pinMode(signalPin, OUTPUT); digitalWrite(signalPin, LOW); // viene posto a LOW pin delayMicroseconds(2); // per 2 microsecondi digitalWrite(signalPin, HIGH); // invia un impulso di trigger delayMicroseconds(10); // di 10 microsecondi digitalWrite(signalPin, LOW); // pone il pin al LOW in attesa che l'impulso torni indietro pinMode(signalPin, INPUT); pulseTime = pulseIn(signalPin, HIGH); // legge l'eco dell'impulso emesso in microsecondi distance = pulseTime/58; // divide la durata per 58 per ottenere la distanza in cm Serial.print("DISTANZA: "); Serial.println(distance); // stampa sul Serial Monitor il valore della distanza return distance; } void avanti(int velocita) { // quando si regola la velocità con PWM, al di sotto del valore 180 il motore non spinge il peso int vel = map(velocita, 0, 100, 180, 255); // vel = 255; // vel = 254; // vel = 0; digitalWrite(motor1Pin, LOW); digitalWrite(motor2Pin, HIGH); analogWrite(enablePin, vel); isAvanti = true; Serial.print("AVANTI - Input: "); Serial.print(velocita); Serial.print(" - Output: "); Serial.println(vel); } void indietro(int velocita) { int vel = map(velocita, 0, 100, 100, 255); vel = 255; digitalWrite(motor1Pin, HIGH); digitalWrite(motor2Pin, LOW); analogWrite(enablePin, vel); isAvanti = false; Serial.print("INDIETRO - Input: "); Serial.print(velocita); Serial.print(" - Output: "); Serial.println(vel); } // mette lo sterzo in posizione centrale void raddrizza() { if(myservo.read()==180) { // da destra al centro myservo.write(50); randNumber = 0; } else if(myservo.read()==0) { // da sinistra al centro myservo.write(110); randNumber = 0; } }
Datasheets
Reference
http://luckylarry.co.uk/arduino-projects/obstacle-avoidance-robot-build-your-own-larrybot/
http://scuola.arduino.cc/it/content/controlla-motore-dc-ponte-h-l293d
http://scuola.arduino.cc/it/content/misuratore-distanza-sensore-ad-ultrasuoni-srf05
dove li collego i led rosso e verde che nello schema non ci sta ?? grazie
avevo collegato i led solo per fare il debug; nel codice che ho postato infatti non c’è menzione dei led perché ho rimosso le parti in cui vengono accesi/spenti
Scusa i condensatori di diversi valori dove vanno inseriti?
A questo link http://blog.andreaventuri.it/wp-content/uploads/2013/01/venturover/drone01.fzz puoi trovare lo schema elettrico dove viene indicata la posizione di ogni componente.
Per aprirlo serve il programma open source Fritzing (http://fritzing.org/)
Grazie mille e un’altra domanda, nello schema elettrico ho notato che hai collegato l’enable pin al pin 9 di arduino mentre nel programma dichiari cosi’ la variabile:
const int enablePin = 11; // H-bridge enable pin
Grazie, era solo una curiosità per capire il codice.
E leggendo ho visto che il pin e’ attaccato ad un pin digitale. Grazie mille in anticipo 🙂
Ciao bel progetto! Avrei solo una domanda:
come si fa per collegare i motori dc normali agli ingranaggi lego??
in questo progetto i motori DC non sono collegati agli ingranaggi Lego, ho acquistato sia i motori che le ruote posteriori a parte. Invece per quanto riguarda lo sterzo, ho unito la testa circolare del servo-motore ad una puleggia Lego con uno spago: questo collegamento non è il massimo perché dà molto gioco allo sterzo, ma attualmente non ho elaborato una soluzione migliore.
ciao andrea io ho provato a realizzarlo ma mi da un problema di caricamento come se non fosse collegato ti volevo chiedere un aiuto anche perche io sono alle primearmi con arduino grazie
alessandro
ciao, posso chiederti se ha avuto problemi a far camminare il robot perfettamente dritto (ho letto che non è banale perché i 2 motori delle ruote motrici devono girare esattamente alla stessa velocità, e inoltre ci possono essere slittamenti)? Quali sono i vantaggi di usare una Tamiya Twin Motor Gearbox piuttosto che comprare separatamente due motori dc e pilotarli?
No, non ho avuto nessun problema di quel tipo e non ho mai letto niente a riguardo. Tra l’altro i pin 1 e 9 del SN754410 (ovvero quelli che regolano la potenza del motore) sono collegati sulla stessa linea, quindi lavorano esattamente in parallelo.
Il vantaggio principale di usare un Tamiya Twin Motor Gearbox è quello di avere i due motori perfettamente allineati sullo stesso asse, cosa che richiede una certa abilità manuale se si volesse costruire da soli un telaio per i due motori.
Ciao dove mi consigli di acquistare il gear box della tamiya ?
io l’avevo comprato qui: http://www.palazzolimodellismo.com/Educational-Tamiya-TWIN-MOTOR-GEARBOX-Cod-70097.1.17.309.gp.67304.uw.aspx
Salve.
Volevo sapere se potevo farlo senza il motore servo e la programmazione come la modificherei? non sono molto bravo a programmare quindi chiedo il vostro aiuto? Grazie mille.
Senza servo motore si elimina lo sterzo, quindi il funzionamento e la meccanica del robot sono differenti. Se hai intenzione di costruirne uno senza servo, ti consiglio di cercare altri progetti in rete. Grazie per l’interessamento.
ciao, il tuo progetto mi ha veramente stupito. avevo una domanda da farti: ho visto che i motori che hai usato te, si possono comprare solo a pezzi, e poi montarli. per questo progetto è obbligatorio usare proprio questi, oppure possiamo usarne altri? e quali mi consiglieresti? tieni conto che sono alle prime armi e non me ne intendo molto di queste cose. grazie
Si possono usare anche altri tipi di motore elettrico, quelli che ho usato io sono abbastanza economici e funzionano bene. In questo momento non saprei consigliarti altri motori in particolare, ma puoi dare un’occhiata qua ad esempio: http://www.pololu.com/category/22/motors-and-gearboxes
you have the code with sensor ultrasonic SRF04?
posso usare il sensore ultra sonico SRF04 però lo schema dovrebbe essere un po diversa, e il code per programmare l’arduino? e ti sto chiedendo aiuto, perché è la prima volta che uso arduino e non sono bravo..
Lo schema elettrico che hai riportato causa un cortocircuito che ha rischiato di bruciare il connettore ,ne potresti caricare uno più completo per favore?
Sei sicuro di avere assemblato il circuito correttamente?
A quale connettore ti riferisci?
Cosa ritieni sia sbagliato nel mio schema?
ciao, posso chiederti quali modifiche andrebbero apportate in caso di utilizzo di un SRF-04 al posto del SRF-05? Grazie in anticipo
Scusami ma io vedo 3 motori due normale è il terzo un servo mottore. Perché? È la prima volta che faccio una macchina in questo modo è vorrei un aiuto
Ciao,
ci sono due motori per muovere la macchina, invece il servo motore viene usato per ruotare lo sterzo.