UNIVERSITÀ DEGLI STUDI DI ROMATOR VERGATA
FACOLTÀ DI INGEGNERIA
CORSO DI LAUREA IN INGEGNERIA
DELL'AUTOMAZIONE
A.A. 2009/2010
Tesi di Laurea
REALIZZAZIONE E CONTROLLO DI UN ROBOT
MOBILE DIFFERENZIALE
RELATORE CANDIDATO
Ing. Daniele Carnevale Moreno Mattia0121909
...alla mia famigliae ad Alessandra.
Indice
Ringraziamenti 1
Introduzione 2
1 Descrizione Hardware 5
1.1 Sensori di sistanza . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Controller Motori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 Led di segnalazione . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.2 Comandi principali del M.M.B.e. . . . . . . . . . . . . . . . . 10
1.3 Motori DC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5 Motorizzazione della torretta . . . . . . . . . . . . . . . . . . . . . . . 14
1.6 Modulo wireless . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7 Scheda ARDUINO . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.7.1 Alimentazione e memorie Arduino . . . . . . . . . . . . . . . . 19
1.7.2 Input e Output . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.8 Circuito di alimentazione . . . . . . . . . . . . . . . . . . . . . . . . . 21
2 Gestione dell'hardware 23
2.1 Gestione dei motori . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
INDICE I
INDICE
2.1.1 Errore di compilazione . . . . . . . . . . . . . . . . . . . . . . 24
2.1.2 Librerie SoftSerial e NewSoftSerial . . . . . . . . . . . . . . . 24
2.1.3 Software gestione motori . . . . . . . . . . . . . . . . . . . . . 27
2.2 Gestione della comunicazione Arduino Matlab . . . . . . . . . . . . . 28
2.2.1 Trasmissione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.2.2 Ricezione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.3 Gestione Sensori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.4 Gestione Servomotore . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3 Applicazioni 38
3.1 Interfaccia graca di comando . . . . . . . . . . . . . . . . . . . . . . 38
3.1.1 Creazione dell'applicazione GUI . . . . . . . . . . . . . . . . . 38
3.1.2 Elaborazione dati . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.2 Modellizzazione del sistema . . . . . . . . . . . . . . . . . . . . . . . 45
3.3 Controllo distanza . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.4 Controllo di posizione . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Conclusioni e sviluppi futuri 54
Appendice 56
Elenco delle gure 79
Bibliograa 80
INDICE II
Ringraziamenti
Grazie al mio relatore per i consigli, il supporto e la partecipazione che ha dimostrato
nel guidarmi in questo mio lavoro, per la sua esperienza e la sua professionalità messe a
mia disposizione. Un grazie speciale anche ai miei compagni di corso, che dall'inizio di
questi tre anni non hanno mai lesinato su un aiuto o un consiglio. Alla mia famiglia
per aver creduto in me e ad Alessandra che ha avuto il coraggio e la pazienza di
aspettare che i miei sforzi e i miei tentativi si trasformassero in Octagon.
Introduzione 1
Introduzione
Il termine ROBOT deriva dalla parola ceca ROBOTA che signica lavoro pesante o
lavoro forzato ed identica una qualsiasi macchina, di forma più o meno antropomor-
fa, in grado di sostituire l'uomo nei lavori più pesanti, noiosi, faticosi o pericolosi.
La robotica è la scienza che cerca di sviluppare, appunto, metodologie che permatta-
no ad una macchina (robot) dotata di opportuni sensori ed attuattori di percepire ed
interagire con l'ambiente esterno e di svolgere funzioni che sarebbero, altrimenti, ad
esclusivo appannaggio dell'uomo.
Numerosi sono i robot progettati e realizzati no ad oggi in campo industriale, me-
dico, militare e nell'ambito della ricerca scientica: quelli controllati in remoto, i
robot autonomi (droni), i robot sequenziali, quelli di formazione ed investigazione e i
microrobot, solo per elencarne alcuni.
Lo scopo del presente lavoro è quello di riprogettare un precedente robot mobi-
le, l'Octagon, per realizzare un gruppo di Robot a basso costo e che siano versatili,
espandibili, ad elevata autonomia e semplici da riprodurre e mantenere. Gli Octagon,
sono stati creati con lo scopo di fornire uno strumento di grande valore didattico e di
rappresentare, in tal modo, un valido canale di comunicazione interdisciplinare.
Gli Octagon sono in grado di comunicare tramite un modulo radio che ha una portata
di 250 metri in linea d'aria ed un consumo molto ridotto. La capacità di comunicazione
è un requisito essenziale per l'implementazione di tutti quegli algoritmi di intelligenza
Introduzione 2
Introduzione
distribuita multi agente, in cui gli agenti comunicano tra di loro per scambiarsi diverse
informazioni (odometriche, stato, ecc..) e coordinarsi.
Il basso costo dell'hardware scelto per la realizzazione dei robot inuisce in modo molto
positivo sulla riproducibilità e li qualica come un'ottima piattaforma per l'immis-
sione sul mercato di agenti mobili che potranno poi essere specializzati per speciche
applicazioni.
L'estrema modularità con cui gli Octagon sono stati progettati li rende totalmente
aperti ad eventuali modiche e, anche se nella loro versione di base dispongono solo
di quattro sensori ad infrarosso, essi sono in grado di utilizzare una vasta gamma di
sensori: pirometrici per il rilevamento di fonti di calore, periferiche per il controllo di
servocomandi, sensori ad ultrasuoni...
Gli Octagon una volta equipaggiati di un sensore di visione, costituiranno un ottimo
strumento di ricerca di elevata complessità, come ad esempio per: la Swarm Robotics,
ossia la robotica degli sciami . Si tratta di una recente disciplina che trae le sue ori-
gini dall'osservazione dei comportamenti di alcuni insetti sociali, organizzati intorno
ad un individuo, la regina, i quali manifestano quella che spesso viene denita intelli-
genza della colonia che dà luogo ad un comportamento collettivo auto-organizzante.
L'aspetto più interessante di questi sistemi sta nell'emergere di un comportamento
globale grazie allo scambio di messaggi tra i singoli individui e senza alcuna azione di
supervisione.
La presente tesi è divisa in tre capitoli.
Nel primo capitolo vengono descritti tutti i moduli ed i componenti elettrici e mec-
canici utilizzati per la costruzione del robot Octagon; in particolare si esporranno le
caratteristiche meccaniche ed elettriche di ognuno, fornendo indicazioni utili riguardo
al loro funzionamento e alla loro compatibilità con gli altri componenti.
Introduzione 3
Introduzione
Nel secondo capitolo si presenteranno tutti i programmi realizzati per la gestione di
ogni modulo: soprattutto lo sviluppo di applicazioni che consentano ai vari dispositi-
vi di comunicare tra di loro in modo da creare un sistema più complesso, robusto ai
disturbi, in grado di svolgere funzioni complesse come il rilevamento di ostacoli e la
comunicazione con macchine di supervisione anche a distanze elevate.
Nel terzo ed ultimo capitolo si spiegherà, inne, la realizzazione delle tre applicazioni
create per il robot: in particolare verrà descritta la creazione di un'interfaccia graca
che permette ad un qualsiasi utente di interagire e comandare il robot. Una volta
che il robot sarà dotato di sensori più sosticati e precisi, quali ad esempio sensori
per la visione articiale, si potrà utilizzare l'applicazione per comandare il robot dalla
postazione remota.
Nelle altre due applicazioni sono stati realizzati dei controlli. Nella prima si è cercato,
con ottimi risultati, di migliorare le prestazioni del motore nel caso in cui venga ri-
chiesta una posizione angolare dell'albero motore ben precisa: a causa dell'inerzia del
motore, essa di per se da scarsi risultati, ma grazie ad un controllo a ciclo chiuso di
questo sottosistema le prestazioni del robot sono state signicativamente migliorate.
Nella seconda applicazione è stato realizzato un programma che permetta al robot
di seguire un oggetto e di rimanere sempre alla stessa distanza da esso. Quest'ul-
tima applicazione, nello specico, è utile per realizzare una delle idee originarie, in
cui si era pensato di utilizzare dei robot Octagon per simulare il comportamento di
più autovetture ferme ad un incrocio in cui è presente un semaforo; in questo caso il
controllo decentralizzato su ogni robot dovrebbe essere in grado di coordinare i robot
massimizzando l'attraversamento dell'incrocio.
Introduzione 4
Capitolo 1
Descrizione Hardware
In questo capitolo verrà descritta la struttura hardware del robot;si spiegherà nel particolare il funzionamento di: controller motoriM.M.B.e, sensori di distanza GP2D12, scheda Arduino, motori DCa 12V, encoder magnetici, modulo per la comunicazione wireless ecircuito di alimentazione.
1.1 Sensori di sistanza
I robot Octagon sono dotati di sensori di distanza SHARP GP2D12, i quali vengono
montati su un supporto in alluminio solidale all'asse di un servomotore che ne pe-
mette la rotazione; tali sensori permettono di rilevare la distanza degli oggetti che
ne riettono il raggio infrarosso. Per permettere a più robot di operare nello stesso
ambiente vengono scelti sensori ad infrarossi rispetto a sensori ad ultrasuono.
La disposizione iniziale, in cui due sensori erano posti due nella parte anteriore del
robot e due nella parte posteriore, è stata modicata posizionando tutti e quattro i sen-
sori nella parte anteriore del robot, alne di poter realizzare una delle tre applicazioni
che verranno di seguito descritte.
I sensori GP2D12 hanno un range di scansione che varia dai 10 agli 80cm; quando
un oggetto si trova all'interno di tale range, riettendo la luce generata dall'emettitore
5
Cap. 1 Descrizione Hardware 1.1 Sensori di sistanza
Figura 1.1: Sensore SHARP GP2D12
a infrarosso, si ha una variazione del segnale analogico (prodotto dal sensore) che è
funzione non lineare della distanza del GP2D12 dall'ostacolo.
Figura 1.2: Package GP2D12
Le caratteristiche principali dei GP2D12 sono le seguenti:
• Range di scansione 10cm - 80cm
• Tensione di alimentazione compresa tra 4.5V e 5.5V
• Consumo medio di corrente di 50mA
6
Cap. 1 Descrizione Hardware 1.2 Controller Motori
• Tempo di risposta medio 39ms
Si riporta di seguito la funzione non lineare che intercorre tra distanza e tensione
generata dal sensore
Figura 1.3: Segnale generato dai sensori GP2D12
La funzione distanza di cui si ha bisogno è l'inversa di quella mostrata in gura
1.3, che è stata invertita e approssimata via software (gura 1.4).
L'approssimazione della curva è stata eettuata in funzione dei punti di massima
variazione del coeciente angolare della stessa.
1.2 Controller Motori
Il motor mind b enhanced (M.M.B.e) è il circuito che si occupa del controllo diretto
dei motori DC a 12V utilizzati per la realizzazione del robot Octagon. I motor mind
comunicano con la scheda Arduino attraverso un'interfaccia seriale TTL del tipo 8N1,
7
Cap. 1 Descrizione Hardware 1.2 Controller Motori
Figura 1.4: Relazione distanza tensione
protocollo che prevede 8 bit di dati, un bit di stop e non ha bit di parità . Il motor
mind supporta correnti di alimentazione elevate, è protetto contro i picchi di tensione,
quelli di corrente e contro il surriscaldamento. Le caratteristiche principali del motor
mind sono:
• Fino a 1.75A di corrente continua (6A di picco);
• Frequenza PWM di 242Hz o 15.5KHz;
• Interfaccia seriale TTL a 2.4KBPS o 9.6KBPS di baud rate;
• Memoria EEPROM accessibile all'utente sia in lettura che in scrittura;
• Filtro PI per implementare il controllo a ciclo chiuso della velocità;
• Led verde per la comunicazione visuale delle istruzioni ricevute;
8
Cap. 1 Descrizione Hardware 1.2 Controller Motori
• Led rosso per la comunicazione visuale delle condizioni di errore.
Per controllare i motori il motor mind deve ricevere delle istruzioni di comando da
un'unità master, che in questo caso è la scheda Arduino. Le istruzioni che il motor
mind riceve sono così strutturate:
• un primo byte di sincronizzazione, il quale rappresenta il numero 85 in base 10
(01010101 in base 2);
• un secondo byte che indica il comando che il motor mind deve eseguire;
• da zero a quattro byte separati per indicare i parametri del comando indicato
nel secondo byte.
1.2.1 Led di segnalazione
Il motor mind presenta due led per la comunicazione visuale: un led verde, indicato
nello schema elettrico come D2 ed un led rosso, indicato nello schema elettrico come
D3. Il led verde si attiva nel momento esatto in cui viene alimentato il motor mind e
nel momento in cui esso riceve un'istruzione corretta, assumendo, in tal modo, anche
funzione di test per il controllo delle istruzioni inviate , come ad esempio il baud rate.
Il led rosso viene, invece, attivato al vericarsi di condizioni di errore ben precise:
• la temperatura sul PCB supera i 175 gradi centigradi;
• la corrente assorbita supera i 6A;
• la tensione di alimentazione dei motori scende sotto i 5.6 volt.
Viene disattivato non appena la condizione di errore scompare.
9
Cap. 1 Descrizione Hardware 1.2 Controller Motori
1.2.2 Comandi principali del M.M.B.e.
I controller M.M.B.e. sono una versione potenziata rispetto ai precedenti M.M.B. e
presentano un set di comandi più ricco e performante. La gura 1.5 presenta l'elenco
di tutti i comandi che possono essere utilizzati sul M.M.B.e
Figura 1.5: Elenco comandi M.M.B.e.
Come si può vedere ci sono due tipologie di comandi: quelli per operare direttamente
sul motore e quelli per stabilire i parametri interni del M.M.B.e., come ad esempio il
comando per impostare i termini kp e ki del ltro PI.
Nella prima tipologia si trovano ad esempio:
• il comando SETDC (comando 3) il quale riceve un parametro il cui valore può
variare da 0 a 255; tale valore seleziona il duty cycle del segnale PWM che andrà
a comandare il motore: ad esempio per impostare un duty cycle del 50% basta
impostare il valore 127;
• il comando SPDCON (comando 4) impone al motore una certa frequenza che può
variare da 0 a 65.535: in questo comando la frequenza viene espressa attraverso
10
Cap. 1 Descrizione Hardware 1.2 Controller Motori
due byte e si ottiene attraverso l'espressione:
frequency = FreqHi ∗ 256 + FreqLo
dove FreqHi e FreqLo sono i due byte trasmessi come parametri del comando.
Una volta trasmesso il comando il motor mind controllerà il motore in due modi
diversi a seconda di come è stato impostato il bit STATUS.PIMODE nel registro
STATUS:
• STATUS.PIMODE = 0. In questa congurazione denita incremento/decre-
mento, di default nel M.M.B.e, il comando SPDCON seleziona la frequenza
desiderata e la velocità di rotazione del motore è gestita nel seguente modo:
viene incrementata se il tachimetro interno al motor mind segnala una veloci-
tà inferiore a quella richiesta; viene decrementata se il tachimetro segnala una
velocità maggiore di quella richiesta.
• STATUS.PIMODE = 1. In questa congurazione il M.M.B.e. esegue un con-
trollo a ciclo chiuso sulla velocità attraverso un controllore PI, i cui parametri
Kp e Ki sono memorizzati nella memoria EEPROM e possono essere modicati
dall'utente.
Il segnale di errore
∆f = fdesiderata − fattuale
è moltiplicato per un termine proporzionale. La somma degli errori calcolati su
una data nestra temporale è poi moltiplicata per un termine integrale e que-
st'ultimo valore viene, inne, sommato al precedente ed il risultato riportato in
un registro a 32 bit, di cui verranno impiegati solo gli 8 bit più signicativi. Gli
8 bit così ottenuti verranno utilizzati per la generazione del nuovo duty cycle del
11
Cap. 1 Descrizione Hardware 1.3 Motori DC
segnale PWM di controllo dei motori. Se la modalità PI è attiva è raccomanda-
ta una frequenza non inferiore a 15 KHz. Il risultato delle operazioni eettuate
sul termine integrale sarà di gran lunga maggiore di 8 bit, pertanto si eettue-
rà il troncamento delle cifre meno signicative tramite divisione per 2n con n
= PISCALER (valore indicato come terzo parametro del comando SPDCON).
Scegliendo valori inopportuni, specialmente sul parametro Ki, si ottiene un con-
trollo del motore non adeguato; ne è un esempio pratico la scelta di un valore
di Ki troppo elevato, la quale causa la carica del termine integrale portando
facilmente il motore in saturazione e generando fastidiose sovraelongazioni.
1.3 Motori DC
Il movimento del robot Octagon avviene tramite due motori, i quali hanno i rispettivi
assi di rotazione coincidenti e discordi. In particolare si è usato un motoriduttore
RHE158-99-100 dotato di soppressore di disturbi VDR sul collettore, cioè di un resi-
store non lineare che, superata la tensione caratteristica per cui è progettato, abbassa
bruscamente la propria resistenza in modo da attenuare ragguardevolmente il disturbo
(questi dispositivi sono infatti chiamati VDR, acronimo di Voltage Dependent Resi-
stor: resistore variabile con la tensione); è dotato, inoltre, di ingranaggi in metallo e
di un asse posteriore del motore sporgente, per l'applicazione di encoders. La dimen-
sione del riduttore e la cassa metallica consentono una coppia molto elevata.
Sono di seguito riportati il disegno con le dimensioni siche del motoriduttore e la
tabella delle caratteristiche tecniche.
12
Cap. 1 Descrizione Hardware 1.4 Encoder
Figura 1.6: Motore DC
Figura 1.7: Caratteristiche Motore DC
1.4 Encoder
I motoriduttori sopra descritti sono dotati di encoder ad eetto hall. Questi sensori di
posizione sono molto stabili termicamente e resistenti alle sollecitazioni meccaniche,
pertanto, nonostante la bassa risoluzione che li caratterizza, sono stati impiegati nel
presente lavoro per l'implementazione del controllo di posizione del robot. Per ogni
giro del motore sono disponibili 3 impulsi, ed essendo il rapporto di riduzione del
motoriduttore pari a 94.37:1 si avranno 283.11 impulsi generati dall'encoder per ogni
giro dell'asse esterno del motoriduttore; la precisione sulla posizione è quindi di 1.27
o 0.75 mm. L'uscita di questi sensori è di tipo open drain con un massimo di 20mA,
ciò signica che per ricevere correttamente un onda quadra dobbiamo inserire una
resistenza di pull-up del valore 10KΩ.
13
Cap. 1 Descrizione Hardware 1.5 Motorizzazione della torretta
Figura 1.8: Schema di collegamento degli encoder
1.5 Motorizzazione della torretta
I sensori di posizione sono collocati su un supporto in alluminio solidale all'asse di
rotazione di un servomotore che ne permette l'orientamento. L'attuale posizionamen-
to dei sensori non permette la scansione a 360 delle distanze degli oggetti intorno al
robot; essi, infatti, sono stati posizionati in modo da poter rilevare la distanza di un
oggetto che si muove davanti al robot, con una congurazione utile per due applica-
zioni che verranno discusse in seguito.
Il servomotore utilizzato può compiere escursioni di 180 con una precisione di 1/4 di
grado. Di seguito è riportato lo schema di collegamento e la tabella delle caratteristi-
che tecniche del servomotore.
Figura 1.9: Caratteristiche servomotore
14
Cap. 1 Descrizione Hardware 1.6 Modulo wireless
Figura 1.10: Servomotore
I servomotori sono controllati mediante un segnale PWM (Pulse width modula-
tion) in cui il valore del duty cycle impone un certo angolo all'asse del servomotore.
Per un controllo ottimale il segnale di controllo deve avere una frequenza di 50HZ.
Come è possibile notare dalla gura 1.11 il periodo dell'onda quadra del segnale di
controllo può variare da 10ms a 25ms. Il duty cycle di tale segnale impone una certa
posizione angolare all'asse della torretta.
Il servomotore montato sul robot sarà controllato dalla scheda Arduino nella qua-
le sono presenti delle librerie che includono le funzioni per il controllo delle uscite
PWM presenti sulla scheda e grazie alle quali si può gestire il servomotore ad alto
livello richiamando una funzione e passando come parametro la posizione angolare
desiderata.
1.6 Modulo wireless
Una delle caratteristiche essenziali del robot Octagon è quella di avere un modulo
radio che permette la comunicazione wireless con un calcolatore no ad una distanza
di circa 250m in linea d'aria. Il modulo radio ER400TRS è un ricetrasmettitore che
trasferisce i dati in modalità half duplex.
L'ER400TRS è un sottosistema a basso consumo costituito da un microcontroller,
un regolatore di tensione ed un trasmettitore FM. Il microcontroller esegue la fun-
15
Cap. 1 Descrizione Hardware 1.6 Modulo wireless
Figura 1.11: Segnale di controllo del servomotore
zione di ricetrasmettitore RF, realizza l'interfaccia di trasferimento dati da e verso la
sorgente tramite I/O seriale e solleva, inoltre, il dispositivo host dal carico di lavoro
derivante dall'ottimizzazione del segnale radio, dal rilevamento degli errori, dalla cor-
rezione dei dati ricevuti in modo errato e dalla trasmissione dei dati in un formato
adatto al canale. Nel modulo è presente una memoria EEPROM programmabile che
permette di registrare i dati relativi alle varie congurazioni delle modalità operative
del ricetrasmettitore. L'ER400TRS è in grado di rilevare l'intensità del segnale rice-
vuto in modo da determinare il valore assoluto della distanza del robot dal calcolatore:
16
Cap. 1 Descrizione Hardware 1.6 Modulo wireless
Figura 1.12: ER400TRS
Figura 1.13: Diagrmma a blocchi del ER400TRS
per questo genera un segnale analogico la cui ampiezza è inversamente proporzionale
all'energia RF presente nella banda passante del ricevitore. L'intensità di questo se-
gnale può variare da 0 (massimo segnale -50dbm) a 1.2V (minimo segnale -105dbm)
ed ha una pendenza di circa 50db/volt. In gura 1.14 è riportato il segnale analogico
descritto.
La velocità della comunicazione seriale è di 19200 bit/sec. Dei buer interni per-
mettono di accodare 192 byte di dati sia in ingresso che in uscita, in attesa che vengano
trasmessi o utilizzati dall'host.
Purtroppo i moduli EasyRadio non consentono una comunicazione full duplex, in
quanto, operando a coppie sulla stessa frequenza sia in trasmissione che in ricezione,
sono costretti a condividere uno dei canali di livello sico: l'etere. Per quanto detto in
precedenza, non avendo la possibilità di trasmettere e ricevere su frequenze dierenti,
il canale di comunicazione wireless sarà half-duplex. Una ovvia soluzione al problema,
17
Cap. 1 Descrizione Hardware 1.7 Scheda ARDUINO
Figura 1.14: Segnale RSSI
sempre utilizzando i moduli ER400TRS, potrebbe essere impiegare due moduli su
ciascun host ed utilizzarli in modalità simplex, ma per contenere i costi e non ridurre
l'autonomia del robot si è scelto di equipaggiare gli Octagon con un solo modulo
EasyRadio e di limitare la dimensione dei frame che transitano nel canale radio.
1.7 Scheda ARDUINO
Tutti i dispositivi elettronici di cui è dotato il robot Octagon sono gestiti dalla scheda
Arduino duemilanove (il nome duemilanove deriva dal fatto che la scheda è in com-
mercio dal 2009). Arduino è dotato di: un microcontrollore ATmega328 a 16MHz;
14 pin digitali che possono essere congurati come ingressi o come uscite digitali e
di queste 14, 6 possono essere utilizzate come uscite PWM; 6 ingressi analogici; un
oscillatore a 16MHz; un collegamento USB; un jack di alimentazione; un header ICSP;
un pulsante di reset.
18
Cap. 1 Descrizione Hardware 1.7 Scheda ARDUINO
Figura 1.15: Schema elettrico Arduino
1.7.1 Alimentazione e memorie Arduino
L'Arduino Duemilanove può essere alimentato o attraverso una connessione USB o
tramite un alimentatore esterno; nel secondo caso si può utilizzare per la connessione
una spina da 2.1 millimetri con centro positivo oppure si possono utilizzare i pin GND e
Vin del connettore di alimentazione. L'alimentazione è selezionata automaticamente.
La tensione che riceve la scheda Arduino può variare dai 6 ai 20V, ma si deve tenere
presente che con alimentazioni sotto i 7V il pin di uscita a 5V fornisce meno di cinque
volt e la scheda può essere instabile; se si alimenta con una tensione maggiore di
12V il regolatore potrebbe riscaldarsi e danneggiare la scheda. E' quindi consigliato
l'intervallo 7 - 12 volt. I robot Octagon sono equipaggiati di una batteria a 12V che
19
Cap. 1 Descrizione Hardware 1.7 Scheda ARDUINO
fornirà anche l'alimentazione, sempre a 12V, all'Arduino.
Il microcontrollore presente sulla scheda è un ATmega328 che dispone di: una memoria
ash di 32KB per memorizzare il codice (di cui 2KB utilizzati per il bootloader); di
una memoria SRAM di 2KB nella quale vengono memorizzate le variabili utilizzate
a run-time dal programma; una memoria EEPROM da 1KB che può essere letta e
scritta con la libreria EEPROM.
1.7.2 Input e Output
I 14 pin digitali presenti sulla scheda possono essere utilizzati sia come ingressi che
come uscite. Ogni pin può fornire o ricevere un massimo di 40mA ed è dotato di una
resistenza di pull-up di 20-50Ω. Alcuni di questi pin hanno funzioni specializzate:
• Serial: 0(RX) e 1(tx), utilizzati per ricevere (RX) e trasmettere (TX) dati seriali
TTL;
• Interrupt esterni: 2 e 3 i quali possono essere congurati per collegare un
interrupt;
• PWM: 5, 6, 9, 10, 11 che forniscono un'uscita PWM ad 8-bit.
La scheda dispone anche di 6 ingressi analogici, ciascuno dei quali fornisce una riso-
luzione di 10 bit.
Di default questi ingressi misurano una tensione in ingresso che varia da 0 a 5V,
ma l'estremo superiore può essere modicato inserendo la tensione desiderata nel pin
AREF (Analog Reference). Il pin reset permette di resettare il microcontrollore.
L'arduino supporta anche altri protocolli di comunicazione come il protocollo I2C e
la comunicazione SPI.
20
Cap. 1 Descrizione Hardware 1.8 Circuito di alimentazione
1.8 Circuito di alimentazione
Il robot Octagon è dotato di una batteria al piombo che fornisce una tensione di
12V sia all'Arduino che ai due Motor mind. Tutti gli altri dispositivi: il modulo
di comunicazione wireless, i sensori di distanza, il servomotore, la parte logica dei
Motor mind e i due encoders sono alimentati con una tensione di 5V. Per ottenere
tale valore sono stati utilizzati due stabilizzatori di tensione LM1117T5.0; in gura
1.16 viene riportato il circuito di alimentazione del robot. Quando tutti i circuiti del
robot sono alimentati si ha un assorbimento massimo di corrente di 800mA che è il
valore massimo di corrente che può assorbire lo stabilizzatore LM1117T, per questo
si è scelto di usarne due invece che uno. Inne in gura 1.17 si riporta lo schema
Figura 1.16: Circuito di alimentazione
elettrico completo del robot Octagon.
21
Cap. 1 Descrizione Hardware 1.8 Circuito di alimentazione
Figura 1.17: Schema elettrico robot Octagon
22
Capitolo 2
Gestione dell'hardware
In questo capitolo verranno descritti i software creati per la gestionedell'hardware e le problematiche riscontrate nelle varie applicazioni
2.1 Gestione dei motori
Nei robot Octagon ogni motore è gestito da un controller M.M.B.e; i controller comu-
nicano e vengono a loro volta gestiti dalla scheda Arduino. Possiamo immaginare il
motor mind come l'unità slave e l'Arduino come l'unità master.
In gura 2.1 viene mostrato lo schema a blocchi della gestione dei motori: il motor
Figura 2.1: Schema a blocchi per la gestione dei motori
mind riceve dal motore il segnale generato dall'encoder magnetico ed invia allo stesso
i segnali di alimentazione; la scheda Arduino comunica con il controller seguendo il
protocollo di comunicazione Seriale TTL 8-N-1, con il quale vengono utilizzati 10-bit
per spedire un singolo byte, di cui 8 sono bit di dati, uno è un bit di start ed un altro
23
Cap. 2 Gestione dell'hardware 2.1 Gestione dei motori
è un bit di stop. I motor mind possono ricevere e trasferire dati ad una velocità di
2400 o 9600 bit/s.
Per ridurre i ritardi si è impostata la comunicazione con un baud/rate di 9600bit/s.
2.1.1 Errore di compilazione
In fase di programmazione della scheda Arduino non può essere però utilizzato lo sche-
ma mostrato in gura 2.1; non si riesce, infatti, ad eseguire l'upload del programma
scritto sull' Arduino e viene restituito, nella nestra di comunicazione un errore; la
scheda Arduino è collegata al pc attraverso la porta USB ed al motor mind attraverso
i pin di comunicazione seriale: dato che sulla scheda c'è un unico circuito integrato
che gestisce la comunicazione seriale e la porta USB, quando si è in questa fase si crea
qualche anomalia elettrica e l'upload non viene eseguito correttamente.
Le possibili soluzioni per risolvere questo problema sono due:
• utilizzare un accoppiatore ottico per trasferire i dati dall'Arduino al M.M.B.e;
• inserire un deviatore sul pin RX dell'Arduino.
Entrambe le soluzioni permettono di scollegare elettricamente l'Arduino dal controller
motori.
2.1.2 Librerie SoftSerial e NewSoftSerial
La scheda Arduino presenta, di default, un pin per la ricezione ed un pin la trasmis-
sione; si è dovuta, quindi, trovare una soluzione anchè la scheda potesse comunicare
in modo seriale con tre diversi dispositivi del robot: i due motor mind ed il modulo
radio. Il problema è stato risolto collegando il modulo radio alla porta seriale di de-
fault dell'Arduino (pin 0 RX, pin 1 TX) ed i due motor mind ad altri 4 pin digitali
24
Cap. 2 Gestione dell'hardware 2.1 Gestione dei motori
gestiti in modo che svolgano il ruolo di porte seriali.
In un primo momento si è pensato di creare delle funzioni che replicassero quelle della
gestione della porta seriale su gli altri pin, realizzando dei programmi che utilizzas-
sero le funzioni generiche digitalRead e digitalWrite per leggere e scrivere byte
trasmessi e ricevuti ad una velocità pressata. Questa soluzione è stata poi abban-
donata: infatti, dopo la creazione della prima funzione che replica la Serial.print
per trasmettere byte dall'Arduino verso i motor mind, si è immediatamente riscon-
trato un rallentamento del programma, e ci si è resi conto che tali funzioni sarebbero
state poco essibili e non avrebbero potuto emulare tutte quelle che possono essere
utilizzate per la gestione della porta seriale. Inoltre per funzioni di ricezione, da parte
dell'Arduino, ci sarebbero stati notevoli problemi a livello di sincronizzazione.
La casa costruttrice della Scheda Arduino fornisce un insieme di librerie che posso-
no essere implementate nel codice per l'esecuzione di funzioni non standard; una di
queste è la libreria SoftSerial che permette, appunto, di utilizzare semplici pin digitali
come porte seriali. In questa libreria ci sono, però, delle limitazioni:
• velicità di lavoro no a 9600 bit/sec;
• funzione Serial.Available() non disponibile;
• perdita dei dati che arrivano quando la funzione Serial.Read() non è stata
invocata.
Esistono, però, anche altre librerie che non sono fornite dalla casa costruttrice di
Arduino, ma che possono essere comunque utilizzate: ne troviamo alcune sul sito di
ARDUINIANA, in particolare la libreria NewSoftSerial che è quella che verrà imple-
mentata nel codice di gestione dei motori per risolvere i problemi di cui sopra. Ri-
spetto alla precedente SoftSerial, che esegue la tecnica del polling in fase di ricezione
25
Cap. 2 Gestione dell'hardware 2.1 Gestione dei motori
con un considerevole rallentamento nell'esecuzione del programma, la NewSoftSerial
introduce notevoli miglioramenti:
1. implementa uno schema di buering circolare per rendere più eciente l'elabo-
razione RX;
2. può essere utilizzata su tutti i pin digitali dell'Arduino;
3. si possono denire simultaneamente più NewSoftwareSerial;
4. presenta una gamma di velocità più ampia;
5. fornisce un ag di overow() per rilevare il l'overow del buer;
6. supporta i processori ad 8 MHz e 20MHz;
7. supporta il software signal inversion.
Nell'uso di questa libreria si deve tener presente un importante accorgimento: la
funzione mySerial.available non può essere utilizzata come condizione logica all'interno
di cicli while, perché questo causerebbe una ricezione errata dei dati.
Figura 2.2: Schema collegamento Arduino motor mind
26
Cap. 2 Gestione dell'hardware 2.1 Gestione dei motori
2.1.3 Software gestione motori
Per completare la descrizione della gestione dei motori si riportano di seguito le
principale parti del codice scritto.
1 #include <NewSoftSer ia l . h>23 #define rxPin_a 44 #define txPin_a 55 #define rxPin_b 76 #define txPin_b 878 NewSoftSer ia l mySerial_a = NewSoftSer ia l ( rxPin_a , txPin_a ) ;9 NewSoftSer ia l mySerial_b = NewSoftSer ia l ( rxPin_b , txPin_b ) ;
In questa parte di codice viene inclusa la libreria NewSoftSerial, vengono deniti i pin
digitali da utilizzare per la comunicazione e le due comunicazioni una per ogni motor
mind.
1 void setup ( )2 3 // de f i n e pin modes f o r tx , rx , l e d p ins :4 pinMode ( rxPin_a , INPUT) ;5 pinMode ( txPin_a , OUTPUT) ;6 pinMode ( rxPin_b , INPUT) ;7 pinMode ( txPin_b , OUTPUT) ;89 // s e t the data ra t e f o r the So f twa r eSe r i a l por t10 S e r i a l . begin (9600) ;11 mySerial_a . begin (9600) ;12 mySerial_b . begin (9600) ;13
Nella funzione di setup della scheda Arduino vengono specializzati i pin per la tra-
smissione e per la ricezione e viene impostato il baud rate della comunicazione.
1 mySerial_b . p r i n t (85 ,BYTE) ;2 mySerial_b . p r i n t (3 ,BYTE) ;3 mySerial_b . p r i n t (150 ,BYTE) ;45 mySerial_b . p r i n t (85 ,BYTE) ;6 mySerial_b . p r i n t (15 ,BYTE) ;7 de lay (10) ;8 for ( i =0; i <3; i++)9 bu f f e r 2 [ i ] = mySerial_b . read ( ) ;
27
Cap. 2 Gestione dell'hardware 2.2 Gestione della comunicazione Arduino Matlab
In questa porzione di codice si fa un esempio di scrittura e lettura di dati sul
Motor mind. Le prime tre righe di codice eseguono il comando SETDC sul M.M.B.e;
la prima è la trasmissione del byte 85, che, come detto in precedenza, è il byte di
sincronizzazione, vengono poi trasmessi il byte 3 che identica il comando da eseguire
ed inne il byte 150 che è il parametro dell'istruzione richiesta ovvero la velocità.
Nella seconda porzione di codice si ha una lettura di alcuni parametri del motor mind,
in particolare dei valori che assumono le variabili Pterm, Iterm, Piscalar. Come sopra
troviamo la trasmissione del byte 85 e del byte 15 che indica, invece, la richiesta di
trasmissione da parte del motor mind verso l'Arduino; viene inserito un ritardo di
10ms e con un ciclo for vengono memorizzati i valori nel vettore buer.
2.2 Gestione della comunicazione Arduino Matlab
In questo paragrafo viene descritta la realizzazione della comunicazione wireless tra
l'Arduino ed il calcolatore, per la quale si è scelto di utilizzare il software Matlab. La
gura 2.3 mostra lo schema a blocchi della comunicazione. Il modulo ER400TRS e
l'antenna che sono connessi al calcolatore sono racchiusi in un unico modulo mentre, il
modulo e l'antenna che sono connessi alla scheda Arduino sono sicamente separati.
I moduli per la comunicazione wireless ER400TRS rendono trasparente la comuni-
cazione gestendo autonomamente i segnali da trasmettere e ricevere ed è per questo
motivo che nei codici Matlab e Arduino si utilizzaranno le comuni funzioni di lettura
e scrittura su porta seriale; la velocità di comunicaizone è di 19200bit/sec.
Per gestire la comunicazione con una porta seriale su Matlab viene denito un oggetto
di tipo porta seriale; l'oggetto contiene tutti i parametri della comunicazione: il Bau-
drate, la porta seriale con cui comunicare, il numero di bit da cui è composto un dato
ed il numero di bit di stop.
28
Cap. 2 Gestione dell'hardware 2.2 Gestione della comunicazione Arduino Matlab
Figura 2.3: Schema a blocchi comunicazione wireless
1 s = s e r i a l ( 'COM6' ) ;2 s e t ( s , ' BaudRate ' , 19200) ;3 s e t ( s , ' DataBits ' , 8) ;4 s e t ( s , ' StopBits ' , 1) ;5 fopen ( s )6 . . . . . comunicazione . . . . .7 f c l o s e ( s )
Prima di iniziare la comunicazione è necessario connettersi alla porta con il comando
fopen(s); terminata la comunicazione ci si disconnette con il comando fclose(s).
2.2.1 Trasmissione
Per trasferire dati dall'Arduino a Matlab si esegue la seguente istruzione :
1 S e r i a l . p r i n t l n ( a l f a ) ;
dove alfa è un numero intero.
Nel caso in cui si vogliano trasmettere più valori, ad esempio gli elementi di un vettore,
si possono scrivere più Serial.println() consecutive (oppure un'unica Serial.println()
all'interno di un ciclo for); è essenziale usare sempre l'istruzione Serial.println(),
perché in fase di ricezione per distinguere la ne di un valore e l'inizio del successivo
si legge il carattere \n che con l'istruzione Serial.print() normale non viene tra-
29
Cap. 2 Gestione dell'hardware 2.2 Gestione della comunicazione Arduino Matlab
smesso.
Per trasmettere dati da Matlab verso Arduino si usa l'istruzione
1 fw r i t e ( s , vector , ' u int16 ' ) ;
dove la variabile vector è un vettore di interi senza segno a 16 bit di dimensione
arbitraria. In questo caso, a dierenza del precedente, per trasmettere più valori
si usa un'unica istruzione che ha come argomento un vettore; come si può vedere
dall'istruzione, gli elementi del vettore vengono trasmessi come interi senza segno a
16-bit e si possono, quindi, spedire valori che vanno da 0 a 65536 (216).
2.2.2 Ricezione
Descriviamo di seguito il funzionamento dei codici che realizzano le due funzioni di
ricezione, i quali, a dierenza delle precedenti applicazioni, sono più complessi perchè
devono rilevare autonomamente il numero di dati che vengono ricevuti.
Entrambe le funzioni restituiscono i dati organizzati in un vettore, in modo da sem-
plicarne poi l'utilizzo.
• Ricezione dei dati provenienti dalla scheda Arduino.
La funzione Matlab che permette di ricevere dati da una porta seriale è la
segeunte:
1 f r ead ( s , x , ' char ' )
in cui il parametro x è un valore intero che identica il numero di caratteri da
ricevere. Questa funzione restituisce un vettore i cui elementi sono le cifre dei
valori trasmessi intervallate dai caratteri di separazione (\n).
Si supponga ora di eseguire il seguente codice su Arduino:
30
Cap. 2 Gestione dell'hardware 2.2 Gestione della comunicazione Arduino Matlab
1 S e r i a l . p r i n t l n (2478) ;2 S e r i a l . p r i n t l n (365) ;
in Matlab si riceve il vettore :
A = [50, 52, 55, 56,−35,−39, 51, 54, 53,−35,−39]
Apparentemente sembra che ci sia un errore, in realtà i singoli caratteri ricevuti
sono espressi nella codica ASCII; è, quindi, suciente convertire il vettore
ottenendone un secondo contenente i valori corretti:
B = [2, 4, 7, 8,−35,−39, 3, 6, 5,−35, 39]
come possiamo notare i caratteri corrispondenti a \n (-35, -39) rimangono co-
stanti.
La successiva operazione consiste nel costruire un vettore i cui elementi sia-
no i dati trasmessi dalla scheda Arduino, nell'esempio il vettore [2478,365];
operazione realizzata attraverso il seguente codice:
1 A = fread ( s , 1 0 , ' char ' ) ;2 B = A− ' 0 ' ;3 NxM = s i z e ( v a l o r i ) ;4 n = NxM(1) ;5 numero_valori = 0 ;6 for i =1:n7 i f ( v a l o r i ( i )==−35)8 numero_valori=numero_valori+1;9 end10 end11 numero_cifre ( numero_valori ) = 0 ;12 pos i z i one_s l a sh ( numero_valori ) = 0 ;13 j =1;14 i =1;15 while ( i<n)16 i f (B( i ) == −35)17 pos i z i one_s l a sh ( j ) = i ;18 j=j +1;19 end20 i f ( j>numero_valori )
31
Cap. 2 Gestione dell'hardware 2.2 Gestione della comunicazione Arduino Matlab
21 i=n ;22 end23 i f ( j<=numero_valori && (B( i ) ~= −35) && (B( i ) ~= −38) )24 numero_cifre ( j ) = numero_cifre ( j )+1;25 end26 i=i +1;27 end28 bu f f e r ( numero_valori ) = 0 ;29 for w=1: numero_valori ;30 for q=1: numero_cifre (w)31 bu f f e r (w) = bu f f e r (w)+B(q +pos i z i one_s l a sh (w)32 −numero_cifre (w)−1)∗10^( numero_cifre (w)−q ) ;33 end34 end
Nel codice vengono deniti due vettori : numero_cifre e posizione_slash;
gli elementi del primo indicano il numero di cifre dei singoli valori da ricevere:
nell'esempio precedente si ha numero_cifre uguale a [4, 3] perchè i numeri 2478
e 365 sono composti rispettivemente da quattro e tre cifre.
Gli elementi del secondo, invece, indicano in quale posizione del vettore compare
il valore -35: nell'esempio si ha posizione_slash uguale a [5, 10].
Combinando poi le informazioni contenute nei vettori descritti si ottiene il
vettore desiderato.
• Ricezione dei dati proveninti da Matlab.
Come detto in precedenza i dati che vengono trasmessi da Matlab verso Arduino
sono a 16-bit; ne consegue che per trasmettere un valore verranno spediti due
byte e in ricezione si avranno, quindi, due valori ricevuti per ogni singolo valore
spedito da Matlab. Se il dato da trasmettere è minore di 256 uno dei due byte
ricevuti sarà nullo perchè è suciente un solo byte per esprimere numeri da
0 a 255; se, invece, il dato è maggiore di 256 verranno ricevuti due byte che
rappresentano il quoziente ed il resto della divisione tra interi valore/256
La funzione seguente realizza la ricezione dei dati su Arduino.
32
Cap. 2 Gestione dell'hardware 2.3 Gestione Sensori
1 i f ( S e r i a l . a v a i l a b l e ( ) >0)2 3 de lay (10) ;4 int bu f f e r [ S e r i a l . a v a i l a b l e ( ) ] ;5 i =0;6 while ( S e r i a l . a v a i l a b l e ( ) )7 8 a = S e r i a l . read ( ) ;9 S e r i a l . p r i n t l n ( a ,DEC) ;10 bu f f e r [ i ] = a ;11 i++;12 13
La funzione Serial.available() restituisce il numero di dati presenti nel buer di
ricezione; se nel buer ci sono dati si verica la condizione logica del primo if e si
può eseguire il resto della funzione. All'interno del costrutto c'è un ritardo di 10ms
perché si deve attendere che tutti i dati vengano memorizzati nel buer e che quindi
la funzione Serial.available() restituisca il valore corretto. Viene denito un vet-
tore di grandezza opportuna e con un ciclo while vengono memorizzati nel vettore
i dati trasmessi dal software Matlab. A dierenza della comunicazione con i motor
mind, ora la funzione Serial.available() si può utilizzare come condizione logica
di un costrutto while, questo perchè si stanno utilizzando le funzioni standard per la
gestione della porta seriale su Arduino e non funzioni della libreria NewSoftSerial.
2.3 Gestione Sensori
I sensori GP2D12 sono collegati agli input analogici della scheda Arduino. La funzione
che legge il valore dei sensori per ricavare la distanza di un oggetto che si trova nel
volume di scansione del robot, viene eseguita ad ogni ciclo della funzione void loop()
di Arduino. Come detto nel paragrafo 1.1 il segnale generato dai sensori è funzione
non lineare della distanza a cui si trova un ostacolo; questa curva caratteristica è stata
33
Cap. 2 Gestione dell'hardware 2.3 Gestione Sensori
approssimata a tratti via software.
Viene ora analizzato il codice che permette di determinare la distanza tra il robot ed
un eventuale ostacolo:
1 int sensorPin_1 = 1 ;2 int sensorValue_1 = 0 ;3 double tensione_1 = 0 ;4 double distanza_ostacolo_1 = 0 ;5 int d i s tanza1 [ ]=0 , 0 , 0 , 0 , 0 ;6 int media=0;7 void setup ( ) 8 void loop ( ) 9 sensorValue_1 = analogRead ( sensorPin_1 ) ;10 tensione_1 = sensorValue_1 ∗5/1023 .0 ;11 i f ( tensione_1 < 0 . 4 )12 distanza_ostacolo_1 = 98 ; 13 i f ( 0 . 4 <= tensione_1 && tensione_1 < 0 .59 )14 distanza_ostacolo_1 = −150∗ tensione_1 + 140 ; 15 i f ( 0 . 59 <= tensione_1 && tensione_1 < 0 .81 )16 distanza_ostacolo_1 = −72∗ tensione_1 + 96 ; 17 i f ( 0 . 81 <= tensione_1 && tensione_1 < 1 .15 )18 distanza_ostacolo_1 = −36.7∗ tensione_1 + 66 ; 19 i f ( 1 . 15 <= tensione_1 && tensione_1 < 1 .63 )20 distanza_ostacolo_1 = −18∗ tensione_1 + 45 ; 21 i f ( 1 . 63 <= tensione_1 && tensione_1 < 2 . 6 )22 distanza_ostacolo_1 = −8∗tensione_1 + 28 .5 ; 23 i f ( 2 . 6 <= tensione_1 )24 distanza_ostacolo_1 = 99 ; 25 d i s tanza1 [4 ]= d i s tanza1 [ 3 ] ;26 d i s tanza1 [3 ]= d i s tanza1 [ 2 ] ;27 d i s tanza1 [2 ]= d i s tanza1 [ 1 ] ;28 d i s tanza1 [1 ]= d i s tanza1 [ 0 ] ;29 d i s tanza1 [0 ]= distanza_ostacolo_1 ;30 d i s tanza2 [4 ]= d i s tanza2 [ 3 ] ;31 d i s tanza2 [3 ]= d i s tanza2 [ 2 ] ;32 d i s tanza2 [2 ]= d i s tanza2 [ 1 ] ;33 d i s tanza2 [1 ]= d i s tanza2 [ 0 ] ;34 d i s tanza2 [0 ]= distanza_ostacolo_1 ;35 i f (36 ( ( ( d i s tanza1 [0]− d i s tanza1 [ 1 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1 [ 1 ] ) <−10)) &&37 ( ( ( d i s tanza1 [0]− d i s tanza1 [ 2 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1 [ 2 ] ) <−10)) &&38 ( ( ( d i s tanza1 [0]− d i s tanza1 [ 3 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1 [ 3 ] ) <−10)) &&39 ( ( ( d i s tanza1 [0]− d i s tanza1 [ 4 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1 [ 4 ] ) <−10)) )40 d i s tanza1 [0 ]= d i s tanza1 [ 1 ] ; 41 media=(d i s tanza1 [0 ]+ d i s tanza1 [1 ]+ d i s tanza1 [3 ]+ d i s tanza1 [2 ]+ d i s tanza1 [ 4 ] )
/5 ;42 i f ( ( ( ( d i s tanza2 [0]− d i s tanza2 [ 1 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 1 ] )
>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 2 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 2 ] )>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 3 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 3 ] )>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 4 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 4 ] )
34
Cap. 2 Gestione dell'hardware 2.3 Gestione Sensori
>−5)) )4344 45 media=di s tanza2 [ 0 ] ;46 d i s tanza1 [4 ]= d i s tanza2 [ 4 ] ;47 d i s tanza1 [3 ]= d i s tanza2 [ 3 ] ;48 d i s tanza1 [2 ]= d i s tanza2 [ 2 ] ;49 d i s tanza1 [1 ]= d i s tanza2 [ 1 ] ;50 d i s tanza1 [0 ]= d i s tanza2 [ 0 ] ;51
Il codice segue i seguenti passi logici:
• denizione dell'ingresso a cui si riceve il segnale proveniente dal sensore;
• lettura del valore di tensione sul pin di ingresso
sensorValue_1 = analogRead(sensorPin_1);
• conversione in segnali digitali da un convertitore A-D a 10 bit dei segnali in
ingresso agli input analogici dell'Arduino.
Per questo ad una tensione di 5V corrisponde il valore 1024 (210)e ad una ten-
sione di 0V corrisponde il valore 0.
Per ottenere, quindi, il valore di tensione corretto, ricevuto sul pin anologico, si
esegue la proporzione:
5 : 1024 = tensione1 : sensorV alue1
• lettura del valore della tensione ricevuta per ottenere il valore numerico della
distanza (espressa in cm), individuazione della porzione di tratto lineare inte-
ressato e successivo calcolo della distanza.
Come si può notare il segnale di tensione ricevuto varia da 0.4V a 2.6V: se si
riceve un valore al di fuori di questo range vengono arbitrariamente assegnati
valori di distanza corrispondenti a 98cm e 99cm.
35
Cap. 2 Gestione dell'hardware 2.3 Gestione Sensori
Nella variabile distanza_ostacolo_1 è ora presente il valore della distanza.
Il segnale trasmesso dai sensori è soggetto a rumore, perciò, lasciando il robot fermo
davanti ad un ostacolo è possibile che si misurino valori di distanza che presentano
una certa oscillazione rispetto al valore corretto. Per eliminare tale rumore si calcola
la media tra cinque misure di distanza: la misura attuale e le ultime quattro misure
calcolate; in tal modo viene, quindi, determinato un nuovo valore di distanza ad ogni
ciclo di scansione e considerando i tempi tipici di esecuzione di una istanza si ha
un aggiornamento della variabile distanza_ostacolo_1 ogni 10ms circa. Dato che i
tempi caratteristici del robot sono, invece, dell'ordine dei secondi la misura attuale e
le quattro precedenti corrispondono tutte alla stessa distanza che c'è tra il robot ed
un ostacolo.
Il valore di distanza misurato ad ogni ciclo può essere, a volte, molto diverso dai
valori misurati in precedenza. Questo delta può derivare da un disturbo sulla misura
o essere conseguenza della rimozione dell'ostacolo da parte di un agente esterno: il
valore deve essere, quindi, ltrato se aetto da disturbo o, al contrario, memorizzato
se rappresentante la misura reale. Per ottenere la corretta misura vengono creati
due vettori contenenti entrambi i quattro valori precedenti ed il valore attuale: nel
primo la misura attuale viene memorizzata indipendentemente dal suo valore; nel
secondo, invece, la misura attuale viene memorizzata solo se il delta che la separa
dalle precedenti non è maggiore di una quantità predenita.
Unendo le informazioni contenute nei due vettori si riesce, in tal modo, ad ottenere
una misura di distanza corretta in cui tutti i disturbi siano ltrati.
36
Cap. 2 Gestione dell'hardware 2.4 Gestione Servomotore
2.4 Gestione Servomotore
Nel software di sviluppo programmi per Arduino è presente la libreria servo.h, conte-
nente le funzioni utili alla gestione dei servomotori.
Per utilizzare questa libreria si seguono i seguenti passi:
• inclusione della libreria attraverso l'istruzione #include <Servo.h> ;
• creazione di un oggetto di tipo servo con l'istruzione Servo myservo; .
Le funzioni principali di questa libreria sono:
• myservo.attach(pin): ssa la variabile myservo al pin passato come argomento
della funzione;
• myservo.write(pos): scrive un valore per il servo controllando l'albero motore di
conseguenza;
• myservo.read(): legge la posizione angolare corrente dell'asse del servomotore.
37
Capitolo 3
Applicazioni
In questo capitolo verranno descritte le tre applicazioni realizzatecon il robot Octagon: il comando tramite pc, la funzione insegui-mento ed il controllo di posizione.Nella prima si è creata un'interfaccia graca per comandare il motodel robot in modo che si muova in tutte le direzioni e con velocitàstabilite dall'utente; con la funzione inseguimento il robot segue au-tonomamente un oggetto in movimento cercando di interporre trasè e l'oggetto sempre la stessa distanza; il controllo posizione è fat-to sui motori e migliora di molto le prestazioni del robot quando sirichiede una posizione angolare ben precisa.
3.1 Interfaccia graca di comando
L'interfaccia graca di comando è stata la prima applicazione che si è ritenuto oppor-
tuno creare; grazie alla trasmissione wireless di istruzioni di vario tipo si rende agevole
comandare il robot da una postazione remota. Essa è stata realizzata utilizzando il
software Matlab ed in particolare l'applicazione GUI (Graphical User Interface).
3.1.1 Creazione dell'applicazione GUI
Per creare un'applicazione GUI si esegue inizialmente l'istruzione guide nella com-
mand window Matlab, da cui appare una nestra che permette di creare un nuovo
progetto o di aprirne uno già esistente. Scegliendo di creare un lavoro ex-novo si ini-
38
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
zierà a lavorare nella nestra mostrata in gura 3.1 Come si può notare, nella parte
Figura 3.1: Finestra di lavoro GUI
sinistra è presente un menù dal quale è possibile selezionare quali componenti inserire
nell'interfaccia graca.
Per il robot Octagon si è scelto di creare l'interfaccia mostrata in gura 3.2 In essa
sono presenti dei pulsanti per attivare il robot e delle caselle di testo per inserire i
parametri dei comandi quali: velocità di movimento; gradi che deve compiere il robot
e verso di rotazione; distanza da percorrere e numero di gradi di rotazione della tor-
retta su cui sono montati i sensori.
Si spiega ora l'eetto di ogni comando sul robot:
• AVANTI: comanda al robot di muoversi in avanti alla velocità specicata nella
casella velocità; con questo comando il robot si ferma solo nel caso in cui arrivi
ad una distanza di 15cm da un oggetto o venga premuto il comando ARRESTO;
39
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
Figura 3.2: Interfaccia robot octagon
• INDIETRO: il robot si muove indietro secondo le stesse modalità del comando
AVANTI;
• ARRESTO: ferma il robot qualunque movimento esso stia compiendo;
• RUOTA ROBOT: comanda al robot di ruotare, sul proprio asse verticale, di
una quantità indicata nella casella gradi e nel verso indicato nella casella verso
rotazione. Se nell'editor c'è il numero 0 la rotazione avviene in senso antiorario,
se c'è 1 avviene la rotazione avviene in senso orario;
• PERCORRI DISTANZA: fa muovere il robot no a compiere la distanza denita
nella casella [ cm ]. Se nella casella verso distanza c'è il numero 1 la distanza è
percorsa in avanti, se c'è 0 la distanza è percorsa all'indietro;
• RUOTA SENSORI: ruota la torretta di una quantità espressa nella casella
[gradi] ;
• ACQUISISCI DISTANZA: viene visualizzata la distanza dell'oggetto che si trova
davanti al robot.
40
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
Creata l'interfaccia in cui sono presenti tutti i componenti, Matlab genera automatica-
mente un M-le che contiene una funzione per ogni elemento presente nell'interfaccia:
nel momento in cui si interagisce con uno di essi (ad esempio viene premuto uno dei
pulsanti), viene richiamata la funzione associata al componente stesso. Per comanda-
re il robot Octagon è suciente utilizzare solo due elementi: pulsanti ed editor di testo.
Le funzioni associate agli editor di testo eseguono un controllo sui valori inseriti,
in particolare vericano che essi appartengano al range ammesso. Si riporta di seguito
il codice associato all'editor Velocità.
1 func t i on ve loc i ta_Cal lback ( hObject , eventdata , handles )2 va l o r e = st r2doub l e ( get ( hObject , ' S t r ing ' ) ) ;3 va l o r e_ve l o c i t=va l o r e +1;4 i f ( va l o r e_ve loc i t >255)5 va l o r e_ve l o c i t = 255 ;6 end7 i f ( isempty ( va l o r e_ve l o c i t ) )8 s e t ( hObject , ' S t r ing ' , ' 0 ' )9 end10 guidata ( hObject , handles ) ;
Quando si preme un pulsante la funzione associata ad esso esegue le seguenti
operazioni:
• lettura delle stringhe presenti negli editor di testo interessati;
• conversione della stringa in un numero double;
• creazione del vettore da trasmettere al robot;
• trasmissione del vettore.
Viene di seguito riportata la funzione associata al pulsante PERCORRI DISTANZA.
1 func t i on percorr i_dis tanza_Cal lback ( hObject , eventdata , handles )2 d i sp l ay perco r r i_d i tanza ;3 a = get ( handles . d i s tanza , ' S t r ing ' ) ;
41
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
4 a = st r2doub l e ( a ) ;5 b = get ( handles . v e l o c i t a , ' S t r ing ' ) ;6 b = st r2doub l e (b) ;7 c = get ( handles . verso_distanza , ' S t r ing ' ) ;8 c = st r2doub l e ( c ) ;9 d i sp l ay ( a ) ;10 ve t t o r e = [1 4 0 0 0 ] ;11 ve t t o r e (3 ) = a ;12 ve t t o r e (4 ) = b ;13 ve t t o r e (5 ) = c ;14 s = s e r i a l ( 'COM6' ) ;15 s e t ( s , ' BaudRate ' , 19200) ;16 s e t ( s , ' DataBits ' , 8) ;17 s e t ( s , ' StopBits ' , 1) ;18 fopen ( s ) ;19 fw r i t e ( s , vet tore , ' u int16 ' ) ;20 f c l o s e ( s ) ;
L'ordine in cui vengono memorizzati i dati all'interno del vettore, che verrà poi tra-
smesso al robot, denisce il protocollo di trasmissione da seguire. Il primo elemento
identica il robot a cui trasferire i dati (il protocollo prevede la trasmissione dei dati
a più robot presenti nello stesso ambiente); il secondo elemento identica il coman-
do che il robot dovrà eseguire. Gli elementi successivi sono, invece, i parametri del
comando dato: se, ad esempio, si è richiesto di percorrere una distanza pressata il
terzo elemento sarà la distanza da percorrere, il quarto la velocità da utilizzare ed il
quinto il verso.
3.1.2 Elaborazione dati
Quando il robot deve essere comandato tramite l'interfaccia creata, viene caricato su
Arduino il programma che si occupa della gestione dei dati ricevuti e dell'azionamento
opportuno dei motori. Questo programma esegue ciclicamente tre passi:
1. lettura del valore di distanza fornito dai sensori;
2. lettura del buer di ricezione del modulo radio;
42
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
3. interpretazione del vettore ricevuto e azionamento dei motori tramite opportune
funzioni.
Le funzioni che vengono richiamate permottono di far eseguire al robot il comando
richiesto da un utente che sta utilizzando l'interfaccia.
• Avanti: è la funzione che viene richiamata quando un utente preme il pulsante
AVANTI. Essa controlla il primo bit del registro di stato di entrambi i motor
mind per controllare il verso di rotazione attuale di ogni singolo motore ed
esegue un cambiamento nel caso un cui la congurazione corrente non produca
un movimento in avanti del robot. Terminato il controllo aziona i motori alla
velocità desiderata;
1 void avant i ( int v e l o c i t a )2 3 int temp=0;4 mySerial_b . p r i n t (85 ,BYTE) ;5 mySerial_b . p r i n t (5 ,BYTE) ;6 de lay (10) ;7 temp=mySerial_b . read ( ) ;8 i f ( temp==40)9 10 mySerial_b . p r i n t (85 ,BYTE) ;11 mySerial_b . p r i n t (1 ,BYTE) ;12 13 mySerial_a . p r i n t (85 ,BYTE) ;14 mySerial_a . p r i n t (5 ,BYTE) ;15 de lay (10) ;16 temp=mySerial_a . read ( ) ;17 i f ( temp==41)18 19 mySerial_a . p r i n t (85 ,BYTE) ;20 mySerial_a . p r i n t (1 ,BYTE) ;21 22 mySerial_a . p r i n t (85 ,BYTE) ;23 mySerial_a . p r i n t (3 ,BYTE) ;24 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;25 mySerial_b . p r i n t (85 ,BYTE) ;26 mySerial_b . p r i n t (3 ,BYTE) ;27 mySerial_b . p r i n t ( v e l o c i t a +7,BYTE) ;
43
Cap. 3 Applicazioni 3.1 Interfaccia graca di comando
• INDIETRO: il robot si muove seguendo la stessa logica adoperata nel comando
Avanti, ma in questo caso retrocedendo;
• ARRESTO: arresta i motori
1 void a r r e s t o ( )2 3 mySerial_a . p r i n t (85 ,BYTE) ;4 mySerial_a . p r i n t (0 ,BYTE) ;5 mySerial_b . p r i n t (85 ,BYTE) ;6 mySerial_b . p r i n t (0 ,BYTE) ;7
• PERCORRI DISTANZA: calcola il numero di passi encoder necessari anchè
la rotazione del motore produca lo spostamento lineare richiesto. Come nella
funzione Avanti si ha il controllo del primo bit del registro di stato.
1 void per co r r i_d i s tanza ( int distanza , int ve l o c i t a , int verso )2 3 int ango lo_rad iant i ;4 int angolo_gradi ;5 ango lo_rad iant i = ( d i s tanza ∗0 .01 ) /0 . 0 27 ;6 angolo_gradi = ango lo_rad iant i ∗180/3 .141457 ;7 double gradiDes = angolo_gradi ;8 double impu l s i =0;9 int numero_giri=0;10 int a l f a ;11 int beta ;12 double k ;13 k = (283 . 0/360 . 0 ) ;14 impu l s i=k∗ gradiDes ;15 i f ( impuls i >256)16 17 numero_giri=impu l s i /256 ;18 a l f a=numero_giri ;19 beta=impuls i −(256∗a ) ;20 21 else
22 23 a l f a =0;24 beta=impu l s i ;25 26 int temp=0;27 mySerial_a . p r i n t (85 ,BYTE) ;28 mySerial_a . p r i n t (6 ,BYTE) ;29 mySerial_a . p r i n t ( a l f a ,BYTE) ;30 mySerial_a . p r i n t ( beta ,BYTE) ;
44
Cap. 3 Applicazioni 3.2 Modellizzazione del sistema
31 mySerial_a . p r i n t l n ( v e l o c i t a ,BYTE) ;32 mySerial_b . p r i n t (85 ,BYTE) ;33 mySerial_b . p r i n t (6 ,BYTE) ;34 mySerial_b . p r i n t ( a l f a ,BYTE) ;35 mySerial_b . p r i n t ( beta ,BYTE) ;36 mySerial_b . p r i n t l n ( v e l o c i t a +7,BYTE) ;37
Nel codice non è riportata la porzione in cui si esegue il controllo del registro di
stato che è uguale a quello della funzione precedente.
• RUOTA ROBOT: come Percorri Distanza, ma, in questo caso, il primo bit del
registro di stato dei due motor mind viene impostato in modo da produrre una
rotazione del robot.
• RUOTA SENSORI: controlla la posizione angolare dell'asse del servomotore.
1 void ruota_sensor i ( int pos )2 3 myservo . wr i t e ( pos ) ;4
3.2 Modellizzazione del sistema
Prima di spiegare le due applicazioni di controllo è opportuno ricavare un modello ma-
tematico del robot. Il robot Octagon può essere rappresentato dallo schema mostrato
in gura 3.3. Il motor mind riceve in ingresso lo scalare 'u' (che può variare tra 0 e
Figura 3.3: Modello matematico del sistema
45
Cap. 3 Applicazioni 3.3 Controllo distanza
255) e fornisce un valore di tensione direttamente proporzionale a tale variabile. Tutta
la parte elettrica del motore è approssimata con un blocco di guadagno di Ke che rice-
vendo la tensione v in entrata fornisce una corrente i. Nei motori a corrente continua
si può approssimare la coppia come una grandezza direttamente proporzionale alla
corrente e quindi attraverso un altro blocco Km si ottiene la coppia motrice fornita
dal motore. A tale valore è poi sottratto quello della coppia di carico opportunamente
diviso per il rapporto di riduzione n ottenendo la coppia utile. L'ultimo blocco, quello
che da la posizione angolare dell'albero motore, è ricavato dalla seguente equazione:
Cu = J · α + d · ω (3.2.1)
dove α e ω sono rispettivamente l'accalerazione e la velocità angolare, J il momento
di inerzia e d il coeciente di attrito. La funzione di trasferimento di questo sistema
non è stata ricavata ma viene presa da una precedente tesi ed è la seguente:
FDT =−0.058122(z − 2.958)
(z − 1)(z − 0.6671)(z2 + 0.548z + 0.2061)(3.2.2)
Su questa FDT sono fatte le due successive applicazioni.
3.3 Controllo distanza
La seconda applicazione realizzata per il robot Octagon è stata la funzione di insegui-
mento. In questo caso il robot interagisce autonomamente con l'ambiente esterno: nel
momento in cui i sensori non rilevano nessun ostacolo il robot rimane fermo, se invece
riscontrano la presenza di un ostacolo il robot si posiziona ad una distanza di 30cm
da esso, indierentemente dal fatto che la distanza iniziale sia minore o maggiore di
30cm.
Per realizzare tale applicazione è stato creato sia un sistema di controllo a ciclo chiuso
di tipo proporzionale.
46
Cap. 3 Applicazioni 3.3 Controllo distanza
Figura 3.4: Schema a blocchi funzione inseguimento
Figura 3.5: Posizionamento sensori
Ad ogni ciclo il programma controlla il valore di distanza fornito dal sensore numero
1 e denisce la variabile errore come la dierenza tra il valore letto dal sensore numero
uno e la costante 30:
errore = distanza1 − 30
la variabile errore è poi moltiplicata per una costante ed il risultato trasmesso alla
funzione del motor mind che controlla la velocità del motoriduttore. Queste appena
descritte sono le operazioni principali del programma, ma vengono eseguite anche altre
istruzioni che stabiliscono, ad esempio, l'avanzamento o la retrocessione del robot, o
rilevano se il valore di velocità esce dal range ammesso dal comando del motor mind.
SETDC.
1 e r r o r e = media−30;2 v e l o c i t a=e r r o r e ∗15 ;3 i f ( ( media==0)&&check1 )4
47
Cap. 3 Applicazioni 3.3 Controllo distanza
5 mySerial_b . p r i n t (85 ,BYTE) ;6 mySerial_b . p r i n t (0 ,BYTE) ;7 mySerial_a . p r i n t (85 ,BYTE) ;8 mySerial_a . p r i n t (0 ,BYTE) ;9 check1=f a l s e ;10 11 i f (media>0)12 13 i f ( ( ( e r ro r e >10) | | ( e r ro re <−10)) )14 15 check=true ;16 17 i f ( check )18 19 check1=true ;20 i f ( e r ro r e <0)21 22 v e l o c i t a=v e l o c i t a ∗(−1) ;23 24 i f ( ( e r ro re >0)&&(temp==40)&&(temp_a==41)) // se l ' e r rore è p o s i t i v o
muovi avan t i25 26 mySerial_b . p r i n t (85 ,BYTE) ;27 mySerial_b . p r i n t (1 ,BYTE) ;28 mySerial_a . p r i n t (85 ,BYTE) ;29 mySerial_a . p r i n t (1 ,BYTE) ;30 temp=41;31 temp_a=40;32 33 i f ( ( e r ro re <0)&&(temp==41)&&(temp_a=40) ) // se l ' e r rore è nega t i vo muovi
i n d i e t r o34 35 mySerial_b . p r i n t (85 ,BYTE) ;36 mySerial_b . p r i n t (1 ,BYTE) ;37 mySerial_a . p r i n t (85 ,BYTE) ;38 mySerial_a . p r i n t (1 ,BYTE) ;39 temp=40;40 temp_a=41;41 42 i f ( v e l o c i t a >240)43 v e l o c i t a =240;44 i f ( v e l o c i t a <80)45 v e l o c i t a =80;46 i f ( ( e r ro re <8)&&(er ro re >−8))47 48 v e l o c i t a =0;49 check=f a l s e ;50 mySerial_b . p r i n t (85 ,BYTE) ;51 mySerial_b . p r i n t (0 ,BYTE) ;52 mySerial_a . p r i n t (85 ,BYTE) ;53 mySerial_a . p r i n t (0 ,BYTE) ;
48
Cap. 3 Applicazioni 3.4 Controllo di posizione
54 55 mySerial_b . p r i n t (85 ,BYTE) ;56 mySerial_b . p r i n t (3 ,BYTE) ;57 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;58 mySerial_a . p r i n t (85 ,BYTE) ;59 mySerial_a . p r i n t (3 ,BYTE) ;60 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;61 62
3.4 Controllo di posizione
Il motor mind ha la possibilità di eseguire una funzione denominata COUNT, che
riceve come parametri due interi x ed y, dove: il parametro x identica il numero di
passi encoder che il motore ruotando dovrà contare ed il parametro y è la velocità a
cui il robot deve muoversi. Questa funzione fornisce al motore una tensione, tale da
produrre una rotazione dell'albero alla velocità stabilita: la tensione viene fornita no
a quando il numero di passi encoder attuali è minore del numero di passi encoder ri-
chiesti; non appena questi due valori coincidono la funzione toglie tensione al motore.
Si deve tener conto del fatto che il motor mind a volte perde la misura di qualche
passo encoder e che l'inerzia del motore produce una rotazione ulteriore dell'albero
motore per il quale esso non si arresta nel momento esatto in cui viene tolta tensione;
ciò causa un errore di posizionamento, errore che cresce all'aumentare del numero di
passi encoder richiesti. Ne consegue che per grandi distanze l'errore accumulato avrà
un valore troppo elevato e non potrà essere trascurato.
L'ultima applicazione è propriamente un controllo di posizione che migliora signi-
cativamente le prestazioni del robot. In questo caso il segnale digitale prodotto
dall'encoder è trasmesso sia al M.M.B.e. sia alla scheda Arduino, che come detto in
precedenza è dotata di due pin per la ricezione di Interrupt esterni. Il segnale prodotto
dall'encoder ad eetto hall è un segnale digitale il cui valore logico 1 corrisponde ad
49
Cap. 3 Applicazioni 3.4 Controllo di posizione
una tensione di circa 1.2V: per ottenere, quindi, un segnale digitale che possa variare
da 0V a 5V si usa un resistore di pull-up come mostrato in gura 3.6. Per gestire
Figura 3.6: Schema collegamento encoder-Arduino
questo segnale di interrupt connesso al pin 3 la scheda Arduino utilizza la funzione
attachInterrupt(1,inc,CHANGE); dove il numero 1 indica l'interrupt del pin 3 (se
ci fosse stato 0 si sarebbe indicato l'interrupt del pin 2), la stringa inc è il nome
della funzione che viene richiamata ogni qualvolta si verica la condizione impostata
come terzo parametro nella funzione attachInterrupt. In questo caso si è imposta-
to CHANGE ovvero la funzione inc è richiamata ogni volta che il segnale di interrupt
esegue una transizione da un livello logico ad un altro. Si possono impostare altre
due modalità RISING e FALLING, in cui la funzione inc è richiamata solo quando si
verica una transizione del segnale da zero ad uno (RISING) o solo quando si verica
una transizione del segnale da uno a zero (FALLING).
Per realizzare l'applicazione è stato creato un piccolo sistema di controllo proporzio-
nale integrale.
1 void ( setup )2 3 a t ta ch In t e r rup t (1 , incremento ,FALLING) ;4 mySerial_b . p r i n t (85 ,BYTE) ;5 mySerial_b . p r i n t (5 ,BYTE) ;6 de lay (10) ;7 temp=mySerial_b . read ( ) ;8 i f ( temp==40)
50
Cap. 3 Applicazioni 3.4 Controllo di posizione
Figura 3.7: Schema a blocchi controllo posizione
9 10 mySerial_b . p r i n t (85 ,BYTE) ;11 mySerial_b . p r i n t (1 ,BYTE) ;12 temp=41;13 14 check=true ;15 16 void loop ( )17 18 e r r o r e= impuls i−encoder ;19 v e l o c i t a=e r r o r e ;20 i f ( ( e r ro re >10) | | ( e r ro r e <−10))21 22 check=true ;23 24 i f ( check )25 26 i f ( e r ro r e <0)27 v e l o c i t a=v e l o c i t a ∗(−1) ;28 2930 i f ( ( e r ro re >0)&&(temp==40))31 32 mySerial_b . p r i n t (85 ,BYTE) ;33 mySerial_b . p r i n t (1 ,BYTE) ;34 temp=41;35 36 i f ( ( e r ro re <0)&&(temp==41))37 38 mySerial_b . p r i n t (85 ,BYTE) ;39 mySerial_b . p r i n t (1 ,BYTE) ;40 temp=40;41 42 i f ( v e l o c i t a >255)43 44 v e l o c i t a =255;45
51
Cap. 3 Applicazioni 3.4 Controllo di posizione
46 i f ( v e l o c i t a <80)47 48 v e l o c i t a =80;49 50 i f ( ( e r ro re <2)&&(er ro re >−2))51 52 v e l o c i t a =0;53 check=f a l s e ;54 55 mySerial_b . p r i n t (85 ,BYTE) ;56 mySerial_b . p r i n t (3 ,BYTE) ;57 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;58 59 de lay (100) ;60 6162 void incremento ( )63 64 i f ( temp==41)65 encoder++;66 i f ( temp==40)67 encoder−−;68
Nel codice sono presenti una serie di controlli per ottenere il movimento corretto del
robot:
• il verso di rotazione del motore è determinato dal valore logico assunto dal primo
bit del registro di stato del motor mind, il quale viene letto e modicato nel caso
in cui il robot debba muoversi nel verso opposto;
• la velocità imposta al robot deve rientrare nel range di ammissibilità della fun-
zione SETDC, la quale ammette solo valori compresi tra 0 e 255; nel caso in cui
l'errore sia molto grande il valore velocità, calcolato come termine proporzionale
rispetto all'errore, esce dal suddetto range ed è saturato al valore massimo am-
missibile, ovvero 255. Cosa analoga accade quando l'errore è piccolo: il robot,
infatti, presenta una massa non trascurabile ed è per questo che valori compresi
52
Cap. 3 Applicazioni 3.4 Controllo di posizione
tra 0 e 80 non producono nessuno spostamento.
Nel codice è riportata, inne, anche la funzioneincremento(), che è la funzione ri-
chiamata da attacInterrupt quando si ha il passaggio del segnale digitale, prodotto
dall'encoder, dal livello logico alto al livello logico basso. Purtroppo questa applica-
zione è stata realizzata per un solo motore, perchè il pin digitale numero 2 (ovvero
l'interrupt 0) ha un assorbimento di corrente troppo elevato e non riesce, quindi, a
rilevare le transizioni presenti nel segnale digitale prodotto dall'encoder.
53
Conclusioni e sviluppi futuri
Con il presente lavoro è stata realizzata un'unità robotica mobile di tipo dierenziale
che potrà essere utilizzata per creare un sistema robotico più complesso nel quale uno
o più robot potranno interagire tra di loro, collaborare con un'unità di supervisione e
controllo o compiere simultaneamente entrambe le cose.
Le scelte hardware hanno permesso di realizzare un'unità economica ed espandibile
al tempo stesso, utilizzabile per la simulazione di sistemi multirobot (ad esempio
un incrocio stradale), sorveglianza, mapping o per rilevazioni di vario genere. In
particolare ogni robot, grazie alla sua modularità, potrà essere ampliato e dotato di
sensori specici per le diverse applicazioni in cui verrà utilizzato.
Le prime modiche che potranno essere applicate al robot sono:
• inserimento di un fotoaccoppiatore tra l'Arduino e il modulo radio ER400TRS;
• studio dell'interrupt 0 per collegare entrambi gli encoders dei motori alla scheda
Arduino;
• trasmissione alla scheda Arduino dei segnali prodotti dai sensori utilizzando il
protocollo di comunicazione I2C, già prevista sul microcontrollore;
• realizzazione di una PCB in modo da avere un sistema più robusto a sollecita-
zioni meccaniche e più stabile elettricamente.
54
Conclusioni e sviluppi futuri
Un'ultima modica potrà essere quella di sostituire l'attuale batteria al piombo con
una più leggera che mantenga la stessa carica elettrica, avendo, però, cura di non uti-
lizzare una batteria eccessivamente leggera che, diminuendo troppo il carico, potrebbe
creare fenomeni di slittameto.
55
Appendice
Listato
Programma per il controllo di posizione sul motore
1 // inc l ude the So f twar eSe r i a l l i b r a r y so you can use i t s f unc t i on s :2 #include <NewSoftSer ia l . h>34 // de f i n e pin o f s e r i a l communications5 #define rxPin_a 46 #define txPin_a 57 #define rxPin_b 78 #define txPin_b 8910 // by t e d i r i c e z i o n e11 byte incomingByte = 0 ;12 int incomingByte1 = 0 ;131415 // s e t up a new s e r i a l por t16 NewSoftSer ia l mySerial_a = NewSoftSer ia l ( rxPin_a , txPin_a ) ;17 NewSoftSer ia l mySerial_b = NewSoftSer ia l ( rxPin_b , txPin_b ) ;1819 boolean check ;20 double gradiDes =1800;21 double impu l s i =0;22 int a=0;23 int a l f a ;24 int beta ;25 int i =0;26 int j =0;27 int bu f f e r 1 [ 2 ] ;28 int v=0;29 double k ;30 volat i le int encoder = 0 ;31 int e r r o r e =0;32 int v e l o c i t a =0;33 int temp=0;34 void setup ( )35
56
Appendice
36 37 a t ta ch In t e r rup t (1 , incremento ,FALLING) ;38 // de f i n e pin modes f o r tx , rx , l e d p ins :39 pinMode ( rxPin_a , INPUT) ;40 pinMode ( txPin_a , OUTPUT) ;41 pinMode ( rxPin_b , INPUT) ;42 pinMode ( txPin_b , OUTPUT) ;4344 // s e t the data ra t e f o r the So f twa r eSe r i a l por t45 S e r i a l . begin (9600) ;46 mySerial_a . begin (9600) ;47 mySerial_b . begin (9600) ;48 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c a l c o l o de i
pa s s i encoder da e s e gu i r e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .49 k = (283 . 11/360 . 0 ) ;50 impu l s i=k∗ gradiDes ;51 i f ( impuls i >256)52 53 a=impu l s i /256 ;54 a l f a=a ;55 beta=impuls i −(256∗a ) ;56 57 else
58 59 a l f a =0;60 beta=impu l s i ;61 62 S e r i a l . p r i n t ( " gradiDes : " ) ;63 S e r i a l . p r i n t l n ( gradiDes ) ;64 S e r i a l . p r i n t ( " impu l s i da e s e gu i r e : " ) ;65 S e r i a l . p r i n t l n ( impu l s i ) ;66 S e r i a l . p r i n t ( " parte i n t e r a de i g i r i e f f e t t u a t i da l motore : " ) ;67 S e r i a l . p r i n t l n ( a ) ;68 S e r i a l . p r i n t ( " a l f a : " ) ;69 S e r i a l . p r i n t l n ( a l f a ) ;70 S e r i a l . p r i n t ( " beta : " ) ;71 S e r i a l . p r i n t l n ( beta ) ;7273 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . movimentazione
de l robo t in avan t i74 mySerial_b . p r i n t (85 ,BYTE) ;75 mySerial_b . p r i n t (5 ,BYTE) ;76 de lay (10) ;77 temp=mySerial_b . read ( ) ;78 i f ( temp==40)79 80 mySerial_b . p r i n t (85 ,BYTE) ;81 mySerial_b . p r i n t (1 ,BYTE) ;82 temp=41;83 84 //
57
Appendice
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85 check=true ;86 8788 void loop ( )89 90 e r r o r e= impuls i−encoder ;91 v e l o c i t a=e r r o r e ;92 i f ( ( e r ro re >10) | | ( e r ro r e <−10))93 94 check=true ;95 96 i f ( check )97 98 /∗99 mySerial_b . p r i n t (85 ,BYTE) ; / / . . . . . . . . . . l e g g i i l r e g i s t r o d i s t a t o100 mySerial_b . p r i n t (5 ,BYTE) ;101 de lay (10) ;102 temp=mySerial_b . read () ;103 ∗/104105 i f ( e r ro re <0)// . . . . . . . . . . . . . . . . . . . . . . . . imponi sempre v e l o c i t à p o s i t i v a106 107 v e l o c i t a=v e l o c i t a ∗(−1) ;108 109110 i f ( ( e r ro re >0)&&(temp==40)) // . . . . . . . . . . se l ' e r rore è p o s i t i v o muovi
avan t i111 112 mySerial_b . p r i n t (85 ,BYTE) ;113 mySerial_b . p r i n t (1 ,BYTE) ;114 temp=41;115 116117 i f ( ( e r ro re <0)&&(temp==41)) // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . se l ' e r rore è
nega t i vo muovi i n d i e t r o118 119 mySerial_b . p r i n t (85 ,BYTE) ;120 mySerial_b . p r i n t (1 ,BYTE) ;121 temp=40;122 123124 i f ( v e l o c i t a >240)125 v e l o c i t a =240;126 i f ( v e l o c i t a <80)127 v e l o c i t a =80;128 i f ( ( e r ro re <2)&&(er ro re >−2))129 v e l o c i t a =0;130 check=f a l s e ; 131
58
Appendice
132133 mySerial_b . p r i n t (85 ,BYTE) ;134 mySerial_b . p r i n t (3 ,BYTE) ;135 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;136137 138 de lay (100) ;139 S e r i a l . p r i n t l n ( e r ro re ,DEC) ;140 /∗ i f ( check==f a l s e )141 142 mySerial_b . p r i n t (85 ,BYTE) ;143 mySerial_b . p r i n t (3 ,BYTE) ;144 mySerial_b . p r i n t (175 ,BYTE) ;145 de lay (1000) ;146 mySerial_b . p r i n t (85 ,BYTE) ;147 mySerial_b . p r i n t (0 ,BYTE) ;148 ∗/149 150151 void incremento ( )152 153 i f ( temp==41)154 encoder++;155 i f ( temp==40)156 encoder−−;157
Programma per la comunicazione con interfaccia graca
1 // inc l ude the So f twar eSe r i a l l i b r a r y so you can use i t s f unc t i on s :2 #include <NewSoftSer ia l . h>3 #include <Servo . h>4 // de f i n e pin o f s e r i a l communications5 #define rxPin_a 46 #define txPin_a 57 #define rxPin_b 78 #define txPin_b 8910 // by t e d i r i c e z i o n e11 byte incomingByte = 0 ;12 int incomingByte1 = 0 ;131415 // s e t up a new s e r i a l por t16 NewSoftSer ia l mySerial_a = NewSoftSer ia l ( rxPin_a , txPin_a ) ;17 NewSoftSer ia l mySerial_b = NewSoftSer ia l ( rxPin_b , txPin_b ) ;1819 // crea t e servo o b j e c t to con t r o l a servo20 // a maximum of e i g h t servo o b j e c t s can be crea t ed21 Servo myservo ;22
59
Appendice
23 byte p inState = 0 ;2425 int grandezza_vettore ;26 int i ;27 int a ;28 int j ;2930 int sensorPin_1 = 1 ; // s e l e c t the input pin f o r the po ten t iometer31 int sensorPin_2 = 2 ; // s e l e c t the input pin f o r the po ten t iometer32 int sensorPin_3 = 3 ;33 int sensorPin_4 = 4 ;3435 int sensorValue_1 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor36 int sensorValue_2 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor37 int sensorValue_3 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor38 int sensorValue_4 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor394041 double tensione_1 = 0 ;42 double tensione_2 = 0 ;43 double tensione_3 = 0 ;44 double tensione_4 = 0 ;454647 double distanza_ostacolo_1 = 0 ;48 double distanza_ostacolo_2 = 0 ;49 double distanza_ostacolo_3 = 0 ;50 double distanza_ostacolo_4 = 0 ;5152 int vet to re_di s tanze [ 4 ] ;5354 void setup ( )55 56 // a t t a che s the servo on pin 9 to the servo o b j e c t57 myservo . attach (9 ) ;5859 // de f i n e pin modes f o r tx , rx , l e d p ins :60 pinMode ( rxPin_a , INPUT) ;61 pinMode ( txPin_a , OUTPUT) ;62 pinMode ( rxPin_b , INPUT) ;63 pinMode ( txPin_b , OUTPUT) ;6465 // s e t the data ra t e f o r the So f twa r eSe r i a l por t66 S e r i a l . begin (19200) ;67 mySerial_a . begin (9600) ;68 mySerial_b . begin (9600) ;69
60
Appendice
70 717273 void loop ( )74 7576 // . . . . . . . . . . . . . . . . . . . . . . . read the va lue from the sensor :77 sensorValue_1 = analogRead ( sensorPin_1 ) ;78 sensorValue_2 = analogRead ( sensorPin_2 ) ;79 sensorValue_3 = analogRead ( sensorPin_3 ) ;80 sensorValue_4 = analogRead ( sensorPin_4 ) ;81 // . . . . . . . . . . . . . . . . . . . . . . . . convers ione va l o r e l e t t o da l sensore in
t ens ione82 tensione_1 = sensorValue_1 ∗5/1023 .0 ;83 tensione_2 = sensorValue_2 ∗5/1023 .0 ;84 tensione_3 = sensorValue_3 ∗5/1023 .0 ;85 tensione_4 = sensorValue_4 ∗5/1023 .0 ;86 // . . . . . . . . . . . . . . . . . . . . convers ione va l o r e l e t t o d i s t an za87 i f ( tensione_1 < 0 . 4 )88 distanza_ostacolo_1 = 0 ; 8990 i f ( 0 . 4 <= tensione_1 && tensione_1 < 0 .59 )91 distanza_ostacolo_1 = −150∗ tensione_1 + 140 ; 9293 i f ( 0 . 59 <= tensione_1 && tensione_1 < 0 .81 )94 distanza_ostacolo_1 = −72∗ tensione_1 + 96 ; 9596 i f ( 0 . 81 <= tensione_1 && tensione_1 < 1 .15 )97 distanza_ostacolo_1 = −36.7∗ tensione_1 + 66 ; 9899 i f ( 1 . 15 <= tensione_1 && tensione_1 < 1 .63 )100 distanza_ostacolo_1 = −18∗ tensione_1 + 45 ; 101102 i f ( 1 . 63 <= tensione_1 && tensione_1 < 2 . 6 )103 distanza_ostacolo_1 = −8∗tensione_1 + 28 .5 ; 104105 i f ( 2 . 6 <= tensione_1 )106 distanza_ostacolo_1 = 1000 ; 107 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−108 i f ( tensione_2 < 0 . 4 )109 distanza_ostacolo_2 = 0 ; 110111 i f ( 0 . 4 <= tensione_2 && tensione_2 < 0 .59 )112 distanza_ostacolo_2 = −150∗ tensione_2 + 140 ; 113114 i f ( 0 . 59 <= tensione_2 && tensione_2 < 0 .81 )115 distanza_ostacolo_2 = −72∗ tensione_2 + 96 ; 116117 i f ( 0 . 81 <= tensione_2 && tensione_2 < 1 .15 )118 distanza_ostacolo_2 = −36.7∗ tensione_2 + 66 ; 119
61
Appendice
120 i f ( 1 . 15 <= tensione_2 && tensione_2 < 1 .63 )121 distanza_ostacolo_2 = −18∗ tensione_2 + 45 ; 122123 i f ( 1 . 63 <= tensione_2 && tensione_2 < 2 . 6 )124 distanza_ostacolo_2 = −8∗tensione_2 + 28 .5 ; 125126 i f ( 2 . 6 <= tensione_2 )127 distanza_ostacolo_2 = 1000 ; 128 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−129 i f ( tensione_3 < 0 . 4 )130 distanza_ostacolo_3 = 0 ; 131132 i f ( 0 . 4 <= tensione_3 && tensione_3 < 0 .59 )133 distanza_ostacolo_3 = −150∗ tensione_3 + 140 ; 134135 i f ( 0 . 59 <= tensione_3 && tensione_3 < 0 .81 )136 distanza_ostacolo_3 = −72∗ tensione_3 + 96 ; 137138 i f ( 0 . 81 <= tensione_3 && tensione_3 < 1 .15 )139 distanza_ostacolo_3 = −36.7∗ tensione_3 + 66 ; 140141 i f ( 1 . 15 <= tensione_3 && tensione_3 < 1 .63 )142 distanza_ostacolo_3 = −18∗ tensione_3 + 45 ; 143144 i f ( 1 . 63 <= tensione_3 && tensione_3 < 2 . 6 )145 distanza_ostacolo_3 = −8∗tensione_3 + 28 .5 ; 146147 i f ( 2 . 6 <= tensione_3 )148 distanza_ostacolo_3 = 1000 ; 149 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−150 i f ( tensione_4 < 0 . 4 )151 distanza_ostacolo_4 = 0 ; 152153 i f ( 0 . 4 <= tensione_4 && tensione_4 < 0 .59 )154 distanza_ostacolo_4 = −150∗ tensione_4 + 140 ; 155156 i f ( 0 . 59 <= tensione_4 && tensione_4 < 0 .81 )157 distanza_ostacolo_4 = −72∗ tensione_4 + 96 ; 158159 i f ( 0 . 81 <= tensione_4 && tensione_4 < 1 .15 )160 distanza_ostacolo_4 = −36.7∗ tensione_4 + 66 ; 161162 i f ( 1 . 15 <= tensione_4 && tensione_4 < 1 .63 )163 distanza_ostacolo_4 = −18∗ tensione_4 + 45 ; 164165 i f ( 1 . 63 <= tensione_4 && tensione_4 < 2 . 6 )166 distanza_ostacolo_4 = −8∗tensione_4 + 28 .5 ; 167168 i f ( 2 . 6 <= tensione_4 )169 distanza_ostacolo_4 = 1000 ; 170 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
62
Appendice
171 /∗ v e t t o r e_d i s t an z e [0]= dis tanza_ostaco lo_1 ;172 v e t t o r e_d i s t an z e [1]= dis tanza_ostaco lo_2 ;173 v e t t o r e_d i s t an z e [2]= dis tanza_ostaco lo_3 ;174 v e t t o r e_d i s t an z e [3]= dis tanza_ostaco lo_4 ;175 S e r i a l . p r i n t (" d i s t an za 1 ") ;176 S e r i a l . p r i n t ( dis tanza_ostacolo_1 , 1 ) ;177 S e r i a l . p r i n t (" | | ") ;178 S e r i a l . p r i n t (" d i s t an za 2 ") ;179 S e r i a l . p r i n t ( dis tanza_ostacolo_1 , 1 ) ;180 S e r i a l . p r i n t (" | | ") ;181 S e r i a l . p r i n t (" d i s t an za 3 ") ;182 S e r i a l . p r i n t ( dis tanza_ostacolo_ ,1 ) ;183 S e r i a l . p r i n t (" | | ") ;184 S e r i a l . p r i n t (" d i s t an za 4 ") ;185 S e r i a l . p r i n t l n ( distanza_ostacolo_4 , 1 ) ;186 de lay (1000) ; ∗/187 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f i n e l e t t u r a s en so r i188189190 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− l e t t u r a da t i da matlab191 i f ( S e r i a l . a v a i l a b l e ( ) >0)192 193 de lay (10) ;194 grandezza_vettore = S e r i a l . a v a i l a b l e ( ) ;195 int bu f f e r [ S e r i a l . a v a i l a b l e ( ) ] ;196 i =0;197 while ( S e r i a l . a v a i l a b l e ( ) )198 199 // S e r i a l . p r i n t (" da t i d i s p o n i b i l i : ") ;200 // S e r i a l . p r i n t l n ( S e r i a l . a v a i l a b l e ( ) ,DEC) ;201 a = S e r i a l . read ( ) ;202 // S e r i a l . p r i n t l n (a ) ;203 bu f f e r [ i ] = a ;204 i++;205 206 for ( i =0; i<grandezza_vettore ; i++)207 208 S e r i a l . p r i n t ( " bu f f e r " ) ;209 S e r i a l . p r i n t ( i ,DEC) ;210 S e r i a l . p r i n t ( " : " ) ;211 S e r i a l . p r i n t l n ( bu f f e r [ i ] ,DEC) ;212 213 i f ( bu f f e r [2]==3) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione avan t i214 215 avant i ( bu f f e r [4 ]+ bu f f e r [ 5 ] ∗ 2 5 6 ) ;216 217 i f ( bu f f e r [2]==2) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione
i n d i e t r o218 219 i n d i e t r o ( bu f f e r [4 ]+ bu f f e r [ 5 ] ∗ 2 5 6 ) ;220
63
Appendice
221 i f ( bu f f e r [2]==1) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ionea r r e s t o
222 223 a r r e s t o ( ) ;224 // S e r i a l . p r i n t l n (" a r r e s t o ") ;225 226 i f ( bu f f e r [2]==4) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione
pe r co r r i d i s t an za227 228 pe r co r r i_d i s tanza ( bu f f e r [4 ]+ bu f f e r [ 5 ]∗256 , bu f f e r [6 ]+ bu f f e r [ 7 ]∗256 ,
bu f f e r [ 8 ] ) ;229 230 i f ( bu f f e r [2]==5) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione ruota
robo t231 232 ruota_robot ( bu f f e r [4 ]+ bu f f e r [ 5 ]∗256 , bu f f e r [ 8 ] , bu f f e r [6 ]+ bu f f e r
[ 7 ] ∗ 2 5 6 ) ;233 234 i f ( bu f f e r [2]==6) //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione ruota
s en so r i235 236 ruota_sensor i ( bu f f e r [ 4 ] ) ;237 238 239 i f (((10< distanza_ostacolo_1 )&&(distanza_ostacolo_1 <15) ) | | ( (10 <
distanza_ostacolo_2 )&&(distanza_ostacolo_2 <15) ) | | ( (10 <distanza_ostacolo_3 )&&(distanza_ostacolo_3 <15) ) | | ( (10 <distanza_ostacolo_4 )&&(distanza_ostacolo_4 <15) ) )
240 241 a r r e s t o ( ) ;242 243 244 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f i n e vo id loop
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−245246247 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione avant i
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−248 void avant i ( int v e l o c i t a )249 250 int temp=0;251 mySerial_b . p r i n t (85 ,BYTE) ;252 mySerial_b . p r i n t (5 ,BYTE) ;253 de lay (10) ;254 temp=mySerial_b . read ( ) ;255 i f ( temp==40)256 257 mySerial_b . p r i n t (85 ,BYTE) ;258 mySerial_b . p r i n t (1 ,BYTE) ;259 260
64
Appendice
261 mySerial_a . p r i n t (85 ,BYTE) ;262 mySerial_a . p r i n t (5 ,BYTE) ;263 de lay (10) ;264 temp=mySerial_a . read ( ) ;265 i f ( temp==41)266 267 mySerial_a . p r i n t (85 ,BYTE) ;268 mySerial_a . p r i n t (1 ,BYTE) ;269 270271272273 mySerial_a . p r i n t (85 ,BYTE) ;274 mySerial_a . p r i n t (3 ,BYTE) ;275 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;276277 mySerial_b . p r i n t (85 ,BYTE) ;278 mySerial_b . p r i n t (3 ,BYTE) ;279 mySerial_b . p r i n t ( v e l o c i t a +7,BYTE) ;280 281 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione ind i e t r o
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−282 void i n d i e t r o ( int v e l o c i t a )283 284285 int temp=0;286 mySerial_b . p r i n t (85 ,BYTE) ;287 mySerial_b . p r i n t (5 ,BYTE) ;288 de lay (10) ;289 temp=mySerial_b . read ( ) ;290 i f ( temp==41)291 292 mySerial_b . p r i n t (85 ,BYTE) ;293 mySerial_b . p r i n t (1 ,BYTE) ;294 295296 mySerial_a . p r i n t (85 ,BYTE) ;297 mySerial_a . p r i n t (5 ,BYTE) ;298 de lay (10) ;299 temp=mySerial_a . read ( ) ;300 i f ( temp==40)301 302 mySerial_a . p r i n t (85 ,BYTE) ;303 mySerial_a . p r i n t (1 ,BYTE) ;304 305306 mySerial_a . p r i n t (85 ,BYTE) ;307 mySerial_a . p r i n t (3 ,BYTE) ;308 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;309 mySerial_b . p r i n t (85 ,BYTE) ;310 mySerial_b . p r i n t (3 ,BYTE) ;
65
Appendice
311 mySerial_b . p r i n t ( v e l o c i t a +7,BYTE) ;312 313314 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione arres to
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−315 void a r r e s t o ( )316 317 // S e r i a l . p r i n t (" e s e gu i a r r e s t o ") ;318 mySerial_a . p r i n t (85 ,BYTE) ;319 mySerial_a . p r i n t (0 ,BYTE) ;320 mySerial_b . p r i n t (85 ,BYTE) ;321 mySerial_b . p r i n t (0 ,BYTE) ;322 323324 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione pe r co r r i
d i s tanza−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−325 void per co r r i_d i s tanza ( int distanza , int ve l o c i t a , int verso )326 327 int d i s tanza1 ;328 d i s tanza1= distanza−d i s tanza ∗ ( 0 . 0 8 ) ;329 int ango lo_rad iant i ;330 int angolo_gradi ;331 ango lo_rad iant i = ( d i s tanza1 ∗0 . 01 ) /0 . 0 27 ;332 angolo_gradi = ango lo_rad iant i ∗180/3 .141457 ;333 // S e r i a l . p r i n t l n ( angolo_gradi ,DEC) ;334 double gradiDes = angolo_gradi ;335 double impu l s i =0;336 int numero_giri=0;337 int a l f a ;338 int beta ;339 int i =0;340 double k ;341342343 k = (283 . 0/360 . 0 ) ;344 impu l s i=k∗ gradiDes ;345 i f ( impuls i >256)346 347 numero_giri=impu l s i /256 ;348 a l f a=numero_giri ;349 beta=impuls i −(256∗a ) ;350 351 else
352 353 a l f a =0;354 beta=impu l s i ;355 356357 int temp=0;358 i f ( ver so==0)359
66
Appendice
360 mySerial_b . p r i n t (85 ,BYTE) ;361 mySerial_b . p r i n t (5 ,BYTE) ;362 de lay (10) ;363 temp=mySerial_b . read ( ) ;364 i f ( temp==40)365 366 mySerial_b . p r i n t (85 ,BYTE) ;367 mySerial_b . p r i n t (1 ,BYTE) ;368 369370 mySerial_a . p r i n t (85 ,BYTE) ;371 mySerial_a . p r i n t (5 ,BYTE) ;372 de lay (10) ;373 temp=mySerial_a . read ( ) ;374 i f ( temp==41)375 376 mySerial_a . p r i n t (85 ,BYTE) ;377 mySerial_a . p r i n t (1 ,BYTE) ;378 379 380381 i f ( ver so==1)382 383 mySerial_b . p r i n t (85 ,BYTE) ;384 mySerial_b . p r i n t (5 ,BYTE) ;385 de lay (10) ;386 temp=mySerial_b . read ( ) ;387 i f ( temp==41)388 389 mySerial_b . p r i n t (85 ,BYTE) ;390 mySerial_b . p r i n t (1 ,BYTE) ;391 392393 mySerial_a . p r i n t (85 ,BYTE) ;394 mySerial_a . p r i n t (5 ,BYTE) ;395 de lay (10) ;396 temp=mySerial_a . read ( ) ;397 i f ( temp==40)398 399 mySerial_a . p r i n t (85 ,BYTE) ;400 mySerial_a . p r i n t (1 ,BYTE) ;401 402 403 mySerial_a . p r i n t (85 ,BYTE) ; // . . . . . . . . . . . . . . . . . . . . . . . . . . e s e gu i comando
COUNT404 mySerial_a . p r i n t (6 ,BYTE) ;405 mySerial_a . p r i n t ( a l f a ,BYTE) ;406 mySerial_a . p r i n t ( beta ,BYTE) ;407 mySerial_a . p r i n t l n ( v e l o c i t a ,BYTE) ;408
67
Appendice
409 mySerial_b . p r i n t (85 ,BYTE) ; // . . . . . . . . . . . . . . . . . . . . . . . . . . e s e gu i comandoCOUNT
410 mySerial_b . p r i n t (6 ,BYTE) ;411 mySerial_b . p r i n t ( a l f a ,BYTE) ;412 mySerial_b . p r i n t ( beta ,BYTE) ;413 mySerial_b . p r i n t l n ( v e l o c i t a +7,BYTE) ;414 415416 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione ruota robot
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−417 void ruota_robot ( int angolo , int segno , int v e l o c i t a )418 419 int d i s tanza ;420 double angolo1 ;421 double angolo1_rad ;422 angolo1 = angolo ;423 angolo1_rad = (3 .141457/180 . 0 ) ∗ angolo1 ;424425 d i s tanza = angolo1_rad ∗0 .115∗100 ;426 S e r i a l . p r i n t l n ( angolo1_rad ,DEC) ;427 int d i s tanza1 ;428 d i s tanza1= distanza−d i s tanza ∗ ( 0 . 0 8 ) ;429 int ango lo_rad iant i ;430 int angolo_gradi ;431 ango lo_rad iant i = ( d i s tanza1 ∗0 . 01 ) /0 . 0 27 ;432 angolo_gradi = ango lo_rad iant i ∗180/3 .141457 ;433 S e r i a l . p r i n t l n ( angolo_gradi ,DEC) ;434 double gradiDes = angolo_gradi ;435 double impu l s i =0;436 int numero_giri=0;437 int a l f a ;438 int beta ;439 int i =0;440 double k ;441442443 k = (283 . 0/360 . 0 ) ;444 impu l s i=k∗ gradiDes ;445 i f ( impuls i >256)446 447 numero_giri=impu l s i /256 ;448 a l f a=numero_giri ;449 beta=impuls i −(256∗a ) ;450 451 else
452 453 a l f a =0;454 beta=impu l s i ;455 456457 int temp=0;
68
Appendice
458 i f ( segno==0)459 460 mySerial_b . p r i n t (85 ,BYTE) ;461 mySerial_b . p r i n t (5 ,BYTE) ;462 de lay (10) ;463 temp=mySerial_b . read ( ) ;464 i f ( temp==41)465 466 mySerial_b . p r i n t (85 ,BYTE) ;467 mySerial_b . p r i n t (1 ,BYTE) ;468 469470 mySerial_a . p r i n t (85 ,BYTE) ;471 mySerial_a . p r i n t (5 ,BYTE) ;472 de lay (10) ;473 temp=mySerial_a . read ( ) ;474 i f ( temp==41)475 476 mySerial_a . p r i n t (85 ,BYTE) ;477 mySerial_a . p r i n t (1 ,BYTE) ;478 479 480481 i f ( segno==1)482 483 mySerial_b . p r i n t (85 ,BYTE) ;484 mySerial_b . p r i n t (5 ,BYTE) ;485 de lay (10) ;486 temp=mySerial_b . read ( ) ;487 i f ( temp==40)488 489 mySerial_b . p r i n t (85 ,BYTE) ;490 mySerial_b . p r i n t (1 ,BYTE) ;491 492493 mySerial_a . p r i n t (85 ,BYTE) ;494 mySerial_a . p r i n t (5 ,BYTE) ;495 de lay (10) ;496 temp=mySerial_a . read ( ) ;497 i f ( temp==40)498 499 mySerial_a . p r i n t (85 ,BYTE) ;500 mySerial_a . p r i n t (1 ,BYTE) ;501 502 503504 mySerial_a . p r i n t (85 ,BYTE) ; // . . . . . . . . . . . . . . . . . . . . . . . . . . e s e gu i comando
COUNT505 mySerial_a . p r i n t (6 ,BYTE) ;506 mySerial_a . p r i n t ( a l f a ,BYTE) ;507 mySerial_a . p r i n t ( beta ,BYTE) ;
69
Appendice
508 mySerial_a . p r i n t l n ( v e l o c i t a ,BYTE) ;509510 mySerial_b . p r i n t (85 ,BYTE) ; // . . . . . . . . . . . . . . . . . . . . . . . . . . e s e gu i comando
COUNT511 mySerial_b . p r i n t (6 ,BYTE) ;512 mySerial_b . p r i n t ( a l f a ,BYTE) ;513 mySerial_b . p r i n t ( beta ,BYTE) ;514 mySerial_b . p r i n t l n ( v e l o c i t a ,BYTE) ;515 516517 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−f unz ione ruota
sensor i−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−518 void ruota_sensor i ( int pos )519 520 myservo . wr i t e ( pos ) ;521
Programma per la funzione di inseguimento
1 // inc l ude the So f twar eSe r i a l l i b r a r y so you can use i t s f unc t i on s :2 #include <NewSoftSer ia l . h>34 // de f i n e pin o f s e r i a l communications5 #define rxPin_a 46 #define txPin_a 57 #define rxPin_b 78 #define txPin_b 8910 // s e t up a new s e r i a l por t11 NewSoftSer ia l mySerial_a = NewSoftSer ia l ( rxPin_a , txPin_a ) ;12 NewSoftSer ia l mySerial_b = NewSoftSer ia l ( rxPin_b , txPin_b ) ;1314 boolean check ;15 boolean check1=f a l s e ;16 int i =0;17 int j =0;18 int bu f f e r 1 [ 2 ] ;19 int e r r o r e =0;20 int v e l o c i t a =0;21 int temp=0;22 int temp_a=0;23 int d i s tanza1 [ ]=0 , 0 , 0 , 0 , 0 ;24 int d i s tanza2 [ ]=0 , 0 , 0 , 0 , 0 ;2526 int distanza1_3 [ ]=0 , 0 , 0 , 0 , 0 ;27 int distanza2_3 [ ]=0 , 0 , 0 , 0 , 0 ;2829 int distanza1_4 [ ]=0 , 0 , 0 , 0 , 0 ;30 int distanza2_4 [ ]=0 , 0 , 0 , 0 , 0 ;3132 int sensorPin_1 = 1 ; // s e l e c t the input pin f o r the po ten t iometer
70
Appendice
33 int sensorPin_2 = 2 ; // s e l e c t the input pin f o r the po ten t iometer34 int sensorPin_3 = 3 ;35 int sensorPin_4 = 4 ;3637 int sensorValue_1 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor38 int sensorValue_2 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor39 int sensorValue_3 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor40 int sensorValue_4 = 0 ; // v a r i a b l e to s t o r e the va lue coming from the
sensor414243 double tensione_1 = 0 ;44 double tensione_2 = 0 ;45 double tensione_3 = 0 ;46 double tensione_4 = 0 ;474849 double distanza_ostacolo_1 = 0 ;50 double distanza_ostacolo_2 = 0 ;51 double distanza_ostacolo_3 = 0 ;52 double distanza_ostacolo_4 = 0 ;5354 int media=0;55 int media3=0;56 int media4=0;575859 void setup ( )6061 62 // de f i n e pin modes f o r tx , rx , l e d p ins :63 pinMode ( rxPin_a , INPUT) ;64 pinMode ( txPin_a , OUTPUT) ;65 pinMode ( rxPin_b , INPUT) ;66 pinMode ( txPin_b , OUTPUT) ;6768 // s e t the data ra t e f o r the So f twa r eSe r i a l por t69 S e r i a l . begin (9600) ;70 mySerial_a . begin (9600) ;71 mySerial_b . begin (9600) ;7273 // . . . . . . . . . . . . . . . . . . . . . . . . movimentazione d e l robo t in avan t i74 mySerial_b . p r i n t (85 ,BYTE) ;75 mySerial_b . p r i n t (5 ,BYTE) ;76 de lay (10) ;77 temp = mySerial_b . read ( ) ;78 i f ( temp==40)79
71
Appendice
80 mySerial_b . p r i n t (85 ,BYTE) ;81 mySerial_b . p r i n t (1 ,BYTE) ;82 temp=41;83 84 // . . . . . . . . . . . . . . . .85 mySerial_a . p r i n t (85 ,BYTE) ;86 mySerial_a . p r i n t (5 ,BYTE) ;87 de lay (10) ;88 temp_a = mySerial_a . read ( ) ;89 i f ( temp_a==41)90 91 mySerial_a . p r i n t (85 ,BYTE) ;92 mySerial_a . p r i n t (1 ,BYTE) ;93 temp_a=40;94 95 mySerial_b . p r i n t (85 ,BYTE) ;96 mySerial_b . p r i n t (0 ,BYTE) ;97 mySerial_a . p r i n t (85 ,BYTE) ;98 mySerial_a . p r i n t (0 ,BYTE) ;99 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100 check=true ;101 102103 void loop ( )104 105106 // . . . . . . . . . . . . . . . . . . . . read the va lue from the sensor :107 sensorValue_1 = analogRead ( sensorPin_1 ) ;108 sensorValue_2 = analogRead ( sensorPin_2 ) ;109 sensorValue_3 = analogRead ( sensorPin_3 ) ;110 sensorValue_4 = analogRead ( sensorPin_4 ) ;111 // . . . . . . . . . . . . . . . . . . . . . . . . . . convers ione va l o r e l e t t o da l sensore in
t ens ione112 tensione_1 = sensorValue_1 ∗5/1023 .0 ;113 tensione_2 = sensorValue_2 ∗5/1023 .0 ;114 tensione_3 = sensorValue_3 ∗5/1023 .0 ;115 tensione_4 = sensorValue_4 ∗5/1023 .0 ;116 // . . . . . . . . . . . . . . . convers ione va l o r e l e t t o d i s t an za117 i f ( tensione_1 < 0 . 4 )118 distanza_ostacolo_1 = 0 ; 119120 i f ( 0 . 4 <= tensione_1 && tensione_1 < 0 .59 )121 distanza_ostacolo_1 = −150∗ tensione_1 + 140 ; 122123 i f ( 0 . 59 <= tensione_1 && tensione_1 < 0 .81 )124 distanza_ostacolo_1 = −72∗ tensione_1 + 96 ; 125126 i f ( 0 . 81 <= tensione_1 && tensione_1 < 1 .15 )127 distanza_ostacolo_1 = −36.7∗ tensione_1 + 66 ; 128129 i f ( 1 . 15 <= tensione_1 && tensione_1 < 1 .63 )
72
Appendice
130 distanza_ostacolo_1 = −18∗ tensione_1 + 45 ; 131132 i f ( 1 . 63 <= tensione_1 && tensione_1 < 2 . 6 )133 distanza_ostacolo_1 = −8∗tensione_1 + 28 .5 ; 134135 i f ( 2 . 6 <= tensione_1 )136 distanza_ostacolo_1 = 1000 ; 137 //−−−−−−−−−−−−−−138 i f ( tensione_2 < 0 . 4 )139 distanza_ostacolo_2 = 0 ; 140141 i f ( 0 . 4 <= tensione_2 && tensione_2 < 0 .59 )142 distanza_ostacolo_2 = −150∗ tensione_2 + 140 ; 143144 i f ( 0 . 59 <= tensione_2 && tensione_2 < 0 .81 )145 distanza_ostacolo_2 = −72∗ tensione_2 + 96 ; 146147 i f ( 0 . 81 <= tensione_2 && tensione_2 < 1 .15 )148 distanza_ostacolo_2 = −36.7∗ tensione_2 + 66 ; 149150 i f ( 1 . 15 <= tensione_2 && tensione_2 < 1 .63 )151 distanza_ostacolo_2 = −18∗ tensione_2 + 45 ; 152153 i f ( 1 . 63 <= tensione_2 && tensione_2 < 2 . 6 )154 distanza_ostacolo_2 = −8∗tensione_2 + 28 .5 ; 155156 i f ( 2 . 6 <= tensione_2 )157 distanza_ostacolo_2 = 1000 ; 158 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−159 i f ( tensione_3 < 0 . 4 )160 distanza_ostacolo_3 = 0 ; 161162 i f ( 0 . 4 <= tensione_3 && tensione_3 < 0 .59 )163 distanza_ostacolo_3 = −150∗ tensione_3 + 140 ; 164165 i f ( 0 . 59 <= tensione_3 && tensione_3 < 0 .81 )166 distanza_ostacolo_3 = −72∗ tensione_3 + 96 ; 167168 i f ( 0 . 81 <= tensione_3 && tensione_3 < 1 .15 )169 distanza_ostacolo_3 = −36.7∗ tensione_3 + 66 ; 170171 i f ( 1 . 15 <= tensione_3 && tensione_3 < 1 .63 )172 distanza_ostacolo_3 = −18∗ tensione_3 + 45 ; 173174 i f ( 1 . 63 <= tensione_3 && tensione_3 < 2 . 6 )175 distanza_ostacolo_3 = −8∗tensione_3 + 28 .5 ; 176177 i f ( 2 . 6 <= tensione_3 )178 distanza_ostacolo_3 = 1000 ; 179 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−180 i f ( tensione_4 < 0 . 4 )
73
Appendice
181 distanza_ostacolo_4 = 0 ; 182183 i f ( 0 . 4 <= tensione_4 && tensione_4 < 0 .59 )184 distanza_ostacolo_4 = −150∗ tensione_4 + 140 ; 185186 i f ( 0 . 59 <= tensione_4 && tensione_4 < 0 .81 )187 distanza_ostacolo_4 = −72∗ tensione_4 + 96 ; 188189 i f ( 0 . 81 <= tensione_4 && tensione_4 < 1 .15 )190 distanza_ostacolo_4 = −36.7∗ tensione_4 + 66 ; 191192 i f ( 1 . 15 <= tensione_4 && tensione_4 < 1 .63 )193 distanza_ostacolo_4 = −18∗ tensione_4 + 45 ; 194195 i f ( 1 . 63 <= tensione_4 && tensione_4 < 2 . 6 )196 distanza_ostacolo_4 = −8∗tensione_4 + 28 .5 ; 197198 i f ( 2 . 6 <= tensione_4 )199 distanza_ostacolo_4 = 1000 ; 200201 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−202 d i s tanza1 [4 ]= d i s tanza1 [ 3 ] ;203 d i s tanza1 [3 ]= d i s tanza1 [ 2 ] ;204 d i s tanza1 [2 ]= d i s tanza1 [ 1 ] ;205 d i s tanza1 [1 ]= d i s tanza1 [ 0 ] ;206 d i s tanza1 [0 ]= distanza_ostacolo_1 ;207 d i s tanza2 [4 ]= d i s tanza2 [ 3 ] ;208 d i s tanza2 [3 ]= d i s tanza2 [ 2 ] ;209 d i s tanza2 [2 ]= d i s tanza2 [ 1 ] ;210 d i s tanza2 [1 ]= d i s tanza2 [ 0 ] ;211 d i s tanza2 [0 ]= distanza_ostacolo_1 ;212 i f ( ( ( ( d i s tanza1 [0]− d i s tanza1 [ 1 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1 [ 1 ] )
<−10)) && ( ( ( d i s tanza1 [0]− d i s tanza1 [ 2 ] ) >10) | | ( ( d i s tanza1 [0]− d i s tanza1[ 2 ] ) <−10)) && ( ( ( d i s tanza1 [0]− d i s tanza1 [ 3 ] ) >10) | | ( ( d i s tanza1 [0]−d i s tanza1 [ 3 ] ) <−10)) && ( ( ( d i s tanza1 [0]− d i s tanza1 [ 4 ] ) >10) | | ( (d i s tanza1 [0]− d i s tanza1 [ 4 ] ) <−10)) )
213 d i s tanza1 [0 ]= d i s tanza1 [ 1 ] ; 214 media=(d i s tanza1 [0 ]+ d i s tanza1 [1 ]+ d i s tanza1 [3 ]+ d i s tanza1 [2 ]+ d i s tanza1 [ 4 ] )
/5 ;215 i f ( ( ( ( d i s tanza2 [0]− d i s tanza2 [ 1 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 1 ] )
>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 2 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 2 ] )>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 3 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 3 ] )>−5))&&((( d i s tanza2 [0]− d i s tanza2 [ 4 ] ) <5)&&((d i s tanza2 [0]− d i s tanza2 [ 4 ] )>−5)) )
216217 218 media=di s tanza2 [ 0 ] ;219 d i s tanza1 [4 ]= d i s tanza2 [ 4 ] ;220 d i s tanza1 [3 ]= d i s tanza2 [ 3 ] ;221 d i s tanza1 [2 ]= d i s tanza2 [ 2 ] ;222 d i s tanza1 [1 ]= d i s tanza2 [ 1 ] ;
74
Appendice
223 d i s tanza1 [0 ]= d i s tanza2 [ 0 ] ;224 225 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−226 distanza1_3 [4 ]= distanza1_3 [ 3 ] ;227 distanza1_3 [3 ]= distanza1_3 [ 2 ] ;228 distanza1_3 [2 ]= distanza1_3 [ 1 ] ;229 distanza1_3 [1 ]= distanza1_3 [ 0 ] ;230 distanza1_3 [0 ]= distanza_ostacolo_3 ;231 distanza2_3 [4 ]= distanza2_3 [ 3 ] ;232 distanza2_3 [3 ]= distanza2_3 [ 2 ] ;233 distanza2_3 [2 ]= distanza2_3 [ 1 ] ;234 distanza2_3 [1 ]= distanza2_3 [ 0 ] ;235 distanza2_3 [0 ]= distanza_ostacolo_3 ;236 i f ( ( ( ( distanza1_3 [0]− distanza1_3 [ 1 ] ) >10) | | ( ( distanza1_3 [0]− distanza1_3
[ 1 ] ) <−10)) && ( ( ( distanza1_3 [0]− distanza1_3 [ 2 ] ) >10) | | ( ( distanza1_3[0]− distanza1_3 [ 2 ] ) <−10)) && ( ( ( distanza1_3 [0]− distanza1_3 [ 3 ] ) >10)| | ( ( distanza1_3 [0]− distanza1_3 [ 3 ] ) <−10)) && ( ( ( distanza1_3 [0]−distanza1_3 [ 4 ] ) >10) | | ( ( distanza1_3 [0]− distanza1_3 [ 4 ] ) <−10)) )
237 distanza1_3 [0 ]= distanza1_3 [ 1 ] ; 238 media3=(distanza1_3 [0 ]+ distanza1_3 [1 ]+ distanza1_3 [3 ]+ distanza1_3 [2 ]+
distanza1_3 [ 4 ] ) /5 ;239 i f ( ( ( ( distanza2_3 [0]− distanza2_3 [ 1 ] ) <5)&&((distanza2_3 [0]−
distanza2_3 [ 1 ] ) >−5))&&(((distanza2_3 [0]− distanza2_3 [ 2 ] ) <5)&&((distanza2_3 [0]− distanza2_3 [ 2 ] ) >−5))&&(((distanza2_3 [0]− distanza2_3[ 3 ] ) <5)&&((distanza2_3 [0]− distanza2_3 [ 3 ] ) >−5))&&(((distanza2_3 [0]−distanza2_3 [ 4 ] ) <5)&&((distanza2_3 [0]− distanza2_3 [ 4 ] ) >−5)) )
240241 242 media3=distanza2_3 [ 0 ] ;243 distanza1_3 [4 ]= distanza2_3 [ 4 ] ;244 distanza1_3 [3 ]= distanza2_3 [ 3 ] ;245 distanza1_3 [2 ]= distanza2_3 [ 2 ] ;246 distanza1_3 [1 ]= distanza2_3 [ 1 ] ;247 distanza1_3 [0 ]= distanza2_3 [ 0 ] ;248 249 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−250 distanza1_4 [4 ]= distanza1_4 [ 3 ] ;251 distanza1_4 [3 ]= distanza1_4 [ 2 ] ;252 distanza1_4 [2 ]= distanza1_4 [ 1 ] ;253 distanza1_4 [1 ]= distanza1_4 [ 0 ] ;254 distanza1_4 [0 ]= distanza_ostacolo_4 ;255 distanza2_4 [4 ]= distanza2_4 [ 3 ] ;256 distanza2_4 [3 ]= distanza2_4 [ 2 ] ;257 distanza2_4 [2 ]= distanza2_4 [ 1 ] ;258 distanza2_4 [1 ]= distanza2_4 [ 0 ] ;259 distanza2_4 [0 ]= distanza_ostacolo_4 ;260 i f ( ( ( ( distanza1_4 [0]− distanza1_4 [ 1 ] ) >10) | | ( ( distanza1_4 [0]− distanza1_4
[ 1 ] ) <−10)) && ( ( ( distanza1_4 [0]− distanza1_4 [ 2 ] ) >10) | | ( ( distanza1_4[0]− distanza1_4 [ 2 ] ) <−10)) && ( ( ( distanza1_4 [0]− distanza1_4 [ 3 ] ) >10)| | ( ( distanza1_4 [0]− distanza1_4 [ 3 ] ) <−10)) && ( ( ( distanza1_4 [0]−distanza1_4 [ 4 ] ) >10) | | ( ( distanza1_4 [0]− distanza1_4 [ 4 ] ) <−10)) )
75
Appendice
261 distanza1_4 [0 ]= distanza1_4 [ 1 ] ; 262 media4=(distanza1_4 [0 ]+ distanza1_4 [1 ]+ distanza1_4 [3 ]+ distanza1_4 [2 ]+
distanza1_4 [ 4 ] ) /5 ;263 i f ( ( ( ( distanza2_4 [0]− distanza2_4 [ 1 ] ) <5)&&((distanza2_4 [0]−
distanza2_4 [ 1 ] ) >−5))&&(((distanza2_4 [0]− distanza2_4 [ 2 ] ) <5)&&((distanza2_4 [0]− distanza2_4 [ 2 ] ) >−5))&&(((distanza2_4 [0]− distanza2_4[ 3 ] ) <5)&&((distanza2_4 [0]− distanza2_4 [ 3 ] ) >−5))&&(((distanza2_4 [0]−distanza2_4 [ 4 ] ) <5)&&((distanza2_4 [0]− distanza2_4 [ 4 ] ) >−5)) )
264265 266 media4=distanza2_4 [ 0 ] ;267 distanza1_4 [4 ]= distanza2_4 [ 4 ] ;268 distanza1_4 [3 ]= distanza2_4 [ 3 ] ;269 distanza1_4 [2 ]= distanza2_4 [ 2 ] ;270 distanza1_4 [1 ]= distanza2_4 [ 1 ] ;271 distanza1_4 [0 ]= distanza2_4 [ 0 ] ;272 273 //−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−274 //media=(dis tanza_ostaco lo_2+dis tanza_ostaco lo_1 ) /2;275 e r r o r e = media−20;276 v e l o c i t a=e r r o r e ∗15 ;277 i f ( ( media==0)&&check1 )278 279 mySerial_b . p r i n t (85 ,BYTE) ;280 mySerial_b . p r i n t (0 ,BYTE) ;281 mySerial_a . p r i n t (85 ,BYTE) ;282 mySerial_a . p r i n t (0 ,BYTE) ;283 check1=f a l s e ;284 285286287 i f (media>0)288 289 i f ( ( ( e r ro r e >10) | | ( e r ro re <−10)) )290 291 check=true ;292 293294 i f ( check )295 296297 check1=true ;298 i f ( e r ro re <0)// . . . . . . . . . . . . . . . . . . . . . . . . imponi sempre v e l o c i t à p o s i t i v a299 300 v e l o c i t a=v e l o c i t a ∗(−1) ;301 302303 i f ( ( e r ro re >0)&&(temp==40)&&(temp_a==41)) // . . . . . . . . . . . . . . . se l ' e r rore è
p o s i t i v o muovi avan t i304 305 mySerial_b . p r i n t (85 ,BYTE) ;
76
Appendice
306 mySerial_b . p r i n t (1 ,BYTE) ;307 mySerial_a . p r i n t (85 ,BYTE) ;308 mySerial_a . p r i n t (1 ,BYTE) ;309310 temp=41;311 temp_a=40;312 313314 i f ( ( e r ro re <0)&&(temp==41)&&(temp_a=40) ) // . . . . . . . . . . . . . . se l ' e r rore è
nega t i vo muovi i n d i e t r o315 316 mySerial_b . p r i n t (85 ,BYTE) ;317 mySerial_b . p r i n t (1 ,BYTE) ;318 mySerial_a . p r i n t (85 ,BYTE) ;319 mySerial_a . p r i n t (1 ,BYTE) ;320 temp=40;321 temp_a=41;322 323324 i f ( v e l o c i t a >240)325 v e l o c i t a =240;326 i f ( v e l o c i t a <80)327 v e l o c i t a =80;328 i f ( ( e r ro re <2)&&(er ro re >−2))329 330 v e l o c i t a =0;331 check=f a l s e ;332 mySerial_b . p r i n t (85 ,BYTE) ;333 mySerial_b . p r i n t (0 ,BYTE) ;334 mySerial_a . p r i n t (85 ,BYTE) ;335 mySerial_a . p r i n t (0 ,BYTE) ;336 337 i f ( ( media3>10)&&(media3<35) )338 339 i f ( v e l o c i t a >150)340 341 mySerial_b . p r i n t (85 ,BYTE) ;342 mySerial_b . p r i n t (3 ,BYTE) ;343 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;344 mySerial_a . p r i n t (85 ,BYTE) ;345 mySerial_a . p r i n t (3 ,BYTE) ;346 mySerial_a . p r i n t ( v e l o c i t a −50,BYTE) ;347 348 else
349 350 mySerial_b . p r i n t (85 ,BYTE) ;351 mySerial_b . p r i n t (3 ,BYTE) ;352 mySerial_b . p r i n t ( v e l o c i t a +50,BYTE) ;353 mySerial_a . p r i n t (85 ,BYTE) ;354 mySerial_a . p r i n t (3 ,BYTE) ;355 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;
77
Appendice
356 357 358 else
359 360 i f ( ( media4>10)&&(media4<35) )361 362 i f ( v e l o c i t a >150)363 364 mySerial_b . p r i n t (85 ,BYTE) ;365 mySerial_b . p r i n t (3 ,BYTE) ;366 mySerial_b . p r i n t ( v e l o c i t a −50,BYTE) ;367 mySerial_a . p r i n t (85 ,BYTE) ;368 mySerial_a . p r i n t (3 ,BYTE) ;369 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;370 371 else
372 373 mySerial_b . p r i n t (85 ,BYTE) ;374 mySerial_b . p r i n t (3 ,BYTE) ;375 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;376 mySerial_a . p r i n t (85 ,BYTE) ;377 mySerial_a . p r i n t (3 ,BYTE) ;378 mySerial_a . p r i n t ( v e l o c i t a +50,BYTE) ;379 380 381 else
382 383 mySerial_b . p r i n t (85 ,BYTE) ;384 mySerial_b . p r i n t (3 ,BYTE) ;385 mySerial_b . p r i n t ( v e l o c i t a ,BYTE) ;386 mySerial_a . p r i n t (85 ,BYTE) ;387 mySerial_a . p r i n t (3 ,BYTE) ;388 mySerial_a . p r i n t ( v e l o c i t a ,BYTE) ;389 390 391 392 393 de lay (100) ;394 // S e r i a l . p r i n t l n (media3 ,DEC) ;395
78
Elenco delle gure
1.1 Sensore SHARP GP2D12 . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Package GP2D12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3 Segnale generato dai sensori GP2D12 . . . . . . . . . . . . . . . . . . 7
1.4 Relazione distanza tensione . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Elenco comandi M.M.B.e. . . . . . . . . . . . . . . . . . . . . . . . . 10
1.6 Motore DC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.7 Caratteristiche Motore DC . . . . . . . . . . . . . . . . . . . . . . . . 13
1.8 Schema di collegamento degli encoder . . . . . . . . . . . . . . . . . . 14
1.9 Caratteristiche servomotore . . . . . . . . . . . . . . . . . . . . . . . 14
1.10 Servomotore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.11 Segnale di controllo del servomotore . . . . . . . . . . . . . . . . . . . 16
1.12 ER400TRS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.13 Diagrmma a blocchi del ER400TRS . . . . . . . . . . . . . . . . . . . 17
1.14 Segnale RSSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.15 Schema elettrico Arduino . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.16 Circuito di alimentazione . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.17 Schema elettrico robot Octagon . . . . . . . . . . . . . . . . . . . . . 22
2.1 Schema a blocchi per la gestione dei motori . . . . . . . . . . . . . . . 23
79
ELENCO DELLE FIGURE ELENCO DELLE FIGURE
2.2 Schema collegamento Arduino motor mind . . . . . . . . . . . . . . . 26
2.3 Schema a blocchi comunicazione wireless . . . . . . . . . . . . . . . . 29
3.1 Finestra di lavoro GUI . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.2 Interfaccia robot octagon . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.3 Modello matematico del sistema . . . . . . . . . . . . . . . . . . . . . 45
3.4 Schema a blocchi funzione inseguimento . . . . . . . . . . . . . . . . 47
3.5 Posizionamento sensori . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.6 Schema collegamento encoder-Arduino . . . . . . . . . . . . . . . . . 50
3.7 Schema a blocchi controllo posizione . . . . . . . . . . . . . . . . . . 51
80
Bibliograa
[1] Danilo Luzi, Progettazione e realizzazione di un robot per lo studio del moto di
formazioni',
81