Ammettetelo: chi, almeno una volta nella vita, non ha desiderato possedere un robot in grado di portargli una lattina di birra e stappargliela? Bene, grazie a Berrino i vostri problemi sono finiti! Infatti, d'ora in poi, potrete essere finalmente un tutt'uno con il vostro divano, senza però dover rinunciare a quel dolce nettare che vi disseta durante gli "intensi" pomeriggi domenicali!
Presentazione
In questo articolo, andrò a descrivere come è stato realizzato il mio progetto del robot porta-birra. Esso sarà in grado di riconoscere un determinato input vocale, procedere fino al punto stabilito, stappare la lattina di birra e porgerla all'utente. Per prima cosa è opportuno spendere due parole sulla struttura generica del robot, fissando subito alcuni punti fermi i quali, poi, verranno approfonditi uno alla volta. Il robot è equipaggiato con un elettronica composta da un Raspberry Pi B+, che si occupa di fare da tramite con il mondo esterno, e da un Arduino Uno, a cui è affidato il compito di svolgere tutte le operazioni fisiche, come il movimento dei vari motori e la gestione dei sensori. Il compito di tradurre le “intenzioni” infatti è affidata a due motori passo-passo (con i relativi circuiti di pilotaggio) e ad un motore a spazzole controllato grazie alla Motor Shield Infineon. Il nome che ho deciso di dargli è un gioco di parole realizzato fondendo insieme sia i nomi di "Raspberry" e "Arduino", sia la parola "beer" che tutti sappiamo cosa significa. Bene! Conclusa questa doverosa premessa, cominciamo!
Materiale utilizzato:
- Arduino Uno R3;
- RaspberryPi B+ con Raspbian modificato dai creatori di Jasper, l'assistente vocale;
- Infineon MotorShield per Arduino;
- Sensore ultrasuoni HC-SR04;
- Motori Passo-Passo (Nema17) con relativi circuiti integrati di pilotaggio (EasyDriver 4.4);
- 2x Batteria Usb per l'alimentazione del Raspberry e dei motori passo-passo;
- 2x Pila da 9V ( per alimentare Arduino e l'altra per alimentare il motore);
- Cavi e connettori vari;
- Una vecchia macchinina radiocomandata opportunamente riadattata.
RaspberryPi e controllo vocale
Per il mio progetto ho fatto uso di un software (al momento disponibile solo per Raspbian, uno dei SO del Raspberry) di riconoscimento vocale, chiamato Jasper. La presentazione e la documentazione di questo software è esaustivamente descritta sul sito degli sviluppatori, ma se volessimo farla in breve possiamo dire che la sua funzione principale è, una volta chiamato col nome “Jasper”, quella di ascoltare i comandi dati vocalmente, interpretarli e lanciare sottoprogrammi opportuni. In particolare, nel mio progetto, il suo compito è quello di mandare in esecuzione uno script Python (chiamato modulo) che a sua volta lancerà un programma in C che, gestendo direttamente la porta GPIO, andrà a dare il segnale di avvio all'Arduino. L'enorme apertura di Jasper permette di aggiungere sempre nuovi moduli semplicemente salvandoli dentro la cartella 'Modules', ponendo come limite semplicemente la fantasia di chi si trova a creare nuove funzionalità. Di seguito sono scritti rispettivamente il codice python del modulo che ho creato e il codice C per la gestione della GPIO.
Beer.py |
import re import osWORDS = ["I","WANT","MY","BEER"]def isValid(text): return bool(re.search(r'\bi want my beer\b',text,re.IGNORECASE))def handle(text,mic,profile): os.system("sudo /home/pi/Desktop/interrupt") message="I'm coming" mic.say(message) |
- La lista WORDS deve contenere esattamente le parole che volete utilizzare come comando.
- La funzione isValid compara il testo tradotto dal segnale vocale con quello all'interno della lista e restituisce true al chiamante se corrispondono.
- La funzione handle contiene il vero e proprio corpo del nostro programma: col il metodo system si invoca il programma in C con la stessa sintassi che si userebbe sul terminale linux. La seconda riga semplicemente dichiara e inizializza la stringa “message” che poi, tramite la chiamata al metodo say viene letta da Jasper.
interrupt.c |
#include <wiringPi.h> int main(){ wiringPiSetup(); pinMode(0,OUTPUT);digitalWrite(0,HIGH); delay(1000); digitalWrite(0,LOW);return 0; } |
Il programma qui sopra è piuttosto autoesplicativo, comunque per chi non fosse molto pratico ci basta dire che una volta importata la libreria per la gestione della GPIO e inizializzata quest'ultima tramite wiringPiSetup si da semplicemente un segnale alto al pin digitale 0 (pin fisico 11), si attende un secondo per essere sicuri che Arduino riesca a identificarlo, e si riporta a 0 semplicemente. Inizialmente avevo pensato di utilizzare un bus come lo SPI o l'I2C, ma con scarso successo: il primo è inutilizzabile in quanto, su Arduino, utilizza gli stessi pin (che sono pin fisici sul microcontrollore) dei controlli della motorshield, mentre il secondo ha una gestione, sempre su Arduino, che poco si prestava alle mie esigenze. Inoltre ci sarebbe stata un'inutile complicazione sia del codice che della rete, perché in fondo ci basta semplicemente un segnale “alto” generico.
NOTA: come vedrete di seguito, io ho collegato direttamente i pin di Arduino con quelli del Raspberry. Questo si può fare solo in questo caso perché è unicamente il Raspberry a inviare segnali, mentre Arduino fa semplicemente da ricevitore. Ricordiamo infatti che il Raspberry ha logica a 3.3V e NON tollera i 5V, mentre Arduino ha logica a 5V ed è in grado di riconoscere il segnale del Raspberry.
Fatto ciò, il Raspberry cessa il suo compito e lascia tutto il resto nelle mani dell'Arduino. Vediamo, quindi, come è stato realizzata tutta la parte restante del robot.
Arduino e attuatori
In tutto questo Arduino è stato sempre in attesa dell'interrupt da Raspberry e una volta ricevuto il segnale, il microcontrollore può iniziare ad eseguire il suo compito. Per prima cosa verifica, tramite il sensore ad ultrasuoni, di non avere ostacoli davanti a sé perché, diciamocelo, non c'è cosa peggiore di vedere cadere la propria birra ancor prima di averla potuta assaggiare! Effettuato tale controllo, se la via è libera, il nostro robot inizierà ad accelerare gradualmente fermandosi solo quando si troverà di fronte ad un ostacolo. Arrivato quindi nella posizione corretta, inizieranno le operazioni di stappo! Il primo motore passo passo, posto sopra la lattina tramite una staffa, imprimerà la forza necessaria ad aprire la birra, mentre il secondo motore provvederà ad azionare un meccanismo che farà ruotare il “braccio” verso l'utente. Fatto ciò, il robot avrà finito e noi potremo finalmente dissetarci.
Ecco qui riportato lo schema del circuito, mentre di seguito riportiamo il codice caricato sull'Arduino, commentato nel dettaglio:
robot.ino |
#define IN_1 3 //inizializza i pin fisici della motorshield #define INH_1 12 #define DCMAX 30 //definisce il valore massimo del duty cyclebyte echoPin=13; // inizializza il pin 13 come pin di “echo” del sensore ultrasuoni byte trigPin=2; //inizializza il pin 2 come pin di “trigger” del sensore ultrasuoni unsigned int distance; // dichiara la variabile che conterrà il valore della distanza da un possibile ostacolo int dc; //dichiara la variabileche conterrà il valore corrente del duty cycle del motore a spazzole int interrupt=A2; // definisce come pin di ingresso dell'interupt il pin analogico A2 int flag; //dichiara la variabile flag che conterrà il valore letto dal pin A2 int dir1=6; //variabile per la direzione del primo motore passo-passo sul pin 6 int dir2=7; //variabile per la direzione del primo motore passo-passo sul pin 7 int step1=8; //variabile per il singolo passo del primo motore passo-passo sul pin 8 int step2=9; //variabile per il singolo passo del secondo motore passo-passo sul pin 9void setup(){pinMode(trigPin, OUTPUT); //imposta il pin di “trigger” come pin di output pinMode(echoPin, INPUT); pinMode(IN_1, OUTPUT); pinMode(INH_1, OUTPUT); pinMode(flag, INPUT); digitalWrite(INH_1,HIGH); //imposta il valore logico alto sul pin INH_1 per inibire il motore a spazzole pinMode(dir1,OUTPUT); pinMode(dir2, OUTPUT); pinMode(step1, OUTPUT); pinMode(step2, OUTPUT); digitalWrite(dir1, LOW); digitalWrite(dir2, LOW); digitalWrite(step1, LOW); digitalWrite(step2, LOW);} void loop(){ delay(1000); //aspetta un secondo int distanza(){ //funzione che calcola la distanza digitalWrite(trigPin, LOW); //mette a zero il pin di trigger return r; void stappa(){ //funzione che stappa e muove la lattina digitalWrite(dir1, LOW); for(i=0; i<1000; i++){ //il primo motore stappa la lattina. } delay(1000); digitalWrite(dir1, HIGH); //cambia il senso di rotazione for(i=0; i<1000; i++){ //il primo motore torna indietro for(i=0; i<1000; i++){ //il secondo motore fa girare il braccio delay(3000); for(i=0; i<1000; i++){ |
Nota: i motori passo-passo utilizzati sono i Nema17, pilotati tramite i circuiti EasyDriver 4.4.
Struttura del robot
Come ultimissima cosa non ci resta altro che parlare dello scheletro del nostro robot. La struttura si basa sull'utilizzo di una vecchia macchinina radiocomandata alla quale ho lasciato semplicemente il motore per muoversi e le ruote. Ho aggiunto un pianale di legno per poter alloggiare tutta l'elettronica, una staffa di ferro che tiene in posizione il motore per stappare e un “braccio” che ha il compito di ruotare e porgere la lattina. Questa è la parte in cui ognuno può metterci un po' del suo personalizzando il robot a suo piacere e a seconda delle esigenze.
Conclusioni
Ecco fatto! A questo punto il Berrino è pronto per potervi servire ogni qualvolta desideriate una bella birra fresca, senza però rinunciare al legame simbiotico sviluppato col proprio divano! Chiaramente è possibile farlo lavorare in versione analcolica, ma sarebbe un po' come andare a fare la spesa con una Ferrari!
Tornando seri per un attimo, ci tenevo a ringraziare tutto lo staff di “Elettronica Open Source” per la possibilità che mi ha dato grazie a questo contest e lo stimolo grazie al quale questo progetto ha visto la luce. Lo ringrazio anche per la motorshiel che mi sarà sicuramente utile per qualche altro progetto!
Qui trovate il video del prototipo funzionante.
Grazie e a presto!
bello, bellissimo!!
un giorno ne costruirò uno anche io!! 🙂
Progetto spettacolare, complimenti Paolo.
Progetto originale e divertente, mi piacerebbe vedere foto o meglio un filmato del robottino ci sono in rete? Sarebbe molto carino ed esplicativo.
Grazie a tutti! Per me il feedback è la cosa più importante! Sono contento che il mio progetto vi piaccia! L’evoluzione di Berrino si è fermata, purtroppo, alla situazione di prototipo funzionante, a causa di un nuovo progetto che mi ha impegnato tempo e schede di prototipazione. Si tratta infatti di un sistema per il monitoraggio dello stato dei miei bonsai, il quale, ciclicamente, carica sulla mia pagina web dedicata umidità del terreno e temperatura delle mie piante. Spero di riuscire a scrivere un paio di articoli, perchè è stato molto più complicato e stimolante di quanto non lo sia stato Berrino 🙂 Grazie ancora a tutti per il supporto!
Attendiamo il nuovo progetto…