Tag
Ho trovato su Ebay, per circa 5-6 euro, un piccolo servo motore modello Tower Pro SG90 che può vantare, nonostante le sue dimensioni ridotte, delle specifiche di tutto rispetto e perciò ho cercato di capire meglio come poteva essere utilizzato. Il funzionamento di un servo motore è abbastanza elementare: un pin la 5V, un pin per la terra, e un pin PWM per comunicare con Arduino.
Software
Quando si lavora con un servo motore, è importante ricordarsi di aggiungere al nostro progetto la libreria Servo.h, grazie alla quale diventa molto semplice controllare il servo, trattandolo come un oggetto. Per poter utilizzare il servo, basta dichiararlo e indicare a quale pin è attaccato:
#include <Servo.h> Servo myservo; // Crea l'oggetto servo void setup() { myservo.attach(9); // Attacca l'oggetto servo al pin 9 }
Et voilà. In programmazione, quando si parla di oggetto, si intende un elemento logico e coerente, ben definito, in genere auto-sufficiente (in grado cioé, di eseguire quanto viene richiesto). Questo significa che – mentre per accendere un LED dobbiamo dire a Arduino: accendi il pin, aspetta, spegni – per gestire un servo basta dire: parti! e lui andrà.
Schema
Qui sotto ho riportato lo schema per il collegamento. È davvero semplice, non vi servirà nemmeno una breadboard, per il momento.
Codice
Proviamo adesso a far muovere il servo, in senso orario e anti-orario. Per farlo ci basterà trasmettere al pin 9 la rotazione desiderata, espressa in gradi.
void loop() { myservo.write(0); delay(1000); myservo.write(90); delay(1000); myservo.write(180); delay(1000); }
Velocità
La libreria Servo.h fornisce delle funzionalità davvero molto elementari. Ad esempio, non c’è un comando per impostare la velocità con la quale si deve muovere il nostro servo!…
Ma senza volere criticare questa libreria, che ci permette comunque di utilizzare il servo con solo una riga di codice, vediamo come aggirare il problema.
Per prima cosa, sposto il servo in posizione centrale, con la funzione servo.writeMicroseconds(1500) – il valore 1500 è arbitrario, su alcuni servo potrebbe essere diverso.
Successivamente, creo un ciclo for che aumenta la posizione in maniera incrementale e imposto una piccola pausa tra un movimento e il successivo. L’effetto finale? Il servo si muoverà più o meno velocemente!
Servo myservo; int velocita = 50; // Un valore da 0 a 100 (da lento a veloce) void setup() { myservo.attach(9); myservo.writeMicroseconds(1500); // Imposto il servo al centro } void loop() { for (int n=0; n<90; n++) // Rotazione 90 gradi, un grado per volta { myservo.write(n); // Faccio muovere il servo di un grado delay(calcolaVelocita()); // Imposto il ritardo prima del movimento } delay(1000); // Attendo prima di ricominciare da capo } int calcolaVelocita() { // Calcolo un ritardo da 120 a 20 ms al variare di velocita return (map(velocita,0,100,120,20)); }
La funzione calcolaVelocita() non fa altro che calcolare il ritardo, espresso in millisecondi, da applicare alla rotazione. L’unica particolarità della funzione è che converte il valore di velocita per così dire al contrario, impostando un ritardo minimo (20ms) se è impostata a 100, e un ritardo massimo (120ms) quando la variabile è 0. È un piccolo trucco 🙂
Potenziometro
Aggiungere un potenziometro per controllare la rotazione del servo è uno dei primi e più comuni esperimenti. Potremmo decidere di spingere un pulsante per far ruotare il servo di un numero di gradi prestabilito, oppure abbinarlo allo sketch Toc toc! Chi è? per fargli alzare il chiavistello della porta ed entrare in casa (è stato fatto, credetemi!), ma usare un potenziometro è il modo più immediato, e semplice, di interagire con il nostro servo.
Per farlo, dobbiamo prima di tutto prendere una breadboard ed aggiungere allo schema il potenziometro. Anche in questo caso, lo schema risultante è davvero semplice.
Per poter funzionare, il potenziometro ha bisogno solo di un collegamento alla 5V, di uno alla terra, e di uno al pin analogico di controllo.
Grazie al nostro potenziometro, adesso possiamo far ruotare il servo verso destra o verso sinistra a piacere. Ecco il codice:
Servo myservo; // Crea l'oggetto servo int triggerPin = A0; // Pin analogico per il potenziometro void setup() { myservo.attach(9); // Attacca l'oggetto servo al pin 9 pinMode(triggerPin,INPUT); // Imposto il potenziometro come input } void loop() { int posizione = analogRead(triggerPin); // Leggo il potenziometro int gradi = calcolaRotazione(posizione); // Converto in gradi myservo.write(gradi); // Faccio muovere il servo } int calcolaRotazione(int posToDeg) { // Converte la lettura del potenziometro (da 0 a 1023) in gradi return (map(posToDeg,0,1023,0,180)); }
PS: purtroppo il mio potenziometro è troppo piccolo per cui va soggetto a oscillazioni che fanno muovere il servo un po’ a casaccio 🙂 Ho aggiunto delay(250); alla fine del loop e qualcosa è migliorato, ma servirebbe un potenziometro serio!
Considerazioni
Un servo, normalmente, ruota soltanto di 180 gradi. Se pensate di avere bisogno di una rotazione completa, di 360 gradi, esistono dei servo speciali a rotazione continua; oppure potete aprire il servo e sostituire l’ingranaggio dell’albero con un ingranaggio diverso, che abbia un passo doppio di quello originale. Ma questo è un hack per uomini veri! Se invece vi serve un servo che ruota senza fermarsi mai, allora state cercando un motore… 😉
NB: a differenza di un motore, il servo può essere molto utile in certe circostanze perché conosce la propria posizione. Per conoscere di quanti gradi è ruotato un servo in qualsiasi momento, potete usare la funzione read(); nel nostro esempio myservo.read();
Processing
Per rendere il tutto più interessante (far ruotare una leva non lo è molto), proveremo ad interagire con il servo grazie a Processing. Nel caso specifico, cercheremo di controllare il funzionamento del servo grazie al mouse del nostro computer.
Ma per farlo, dovrete aspettare il prossimo studio. A presto!
Codice: Arduino_Servo_Suite.zip
PS: un saluto dalla mia piccola aiutante Mimi, special guest del video! 🙂
PPS: Come promesso, è ora disponibile lo studio su Arduino servo e Processing.
Valentino Litrico ha detto:
salve.. volevo provare un servo di quel tipo.. costano poco e promettono tanto,
sono affidabili?
cosa succede se per caso si invia un valore superiore a 180° al servo?
ha un blocco meccanico o altro?
grazie 🙂
studioarduino ha detto:
Ciao Valentino! Il servo utilizzato nello studio, secondo me, è un buon prodotto: costa il giusto e funziona senza nessun problema. Però dipende per cosa ti serve: non credo che possa spostare carichi troppo pesanti, ma se ti serve per uno sterzo o per piccoli meccanismi, mi sento di consigliarlo. Se invii al servo una rotazione maggiore di 180° non succede nulla, semplicemente il servo ruota fino a dove può arrivare. Continua a seguirci!
Antonio ha detto:
Salve, voglio utilizzare un servo per l’apertura di una porticina (modellino). Mi piacerebbe che si aprisse tutta quando schiaccio un pulsante e che si richiudesse quando ne schiaccio un altro. Oppure che tenendo premuto un pulsante faccio aprire la porta dell’angolo che più mi aggrada e al rilascio il servo si ferma. spero di essere stato chiaro. è possibile fare una cosa del genere? se si come? grazie mille ancora per la disponibilità
studioarduino ha detto:
Il codice che trovi negli esempi contiene già alcune parti di quello che ti serve. Se decidi che la porticina si deve aprire completamente premendo il pulsante, puoi scrivere qualcosa tipo: if (pulsante==HIGH) { servo.write(90); } in modo da azionare il servo quando premi il pulsante e farlo ruotare di 90 gradi. Se invece vuoi che la porticina si apra un po’ alla volta mentre tieni premuto il pulsante, devi usare un ciclo for, ed impostarlo con un piccolo ritardo (guarda l’esempio dove dice “rotazione, un grado per volta”). In questo caso, dovresti scrivere qualcosa del tipo: while (pulsante==HIGH) { int angolo=servo.read(); servo.write(angolo++); delay(100); } così, tenendo premuto il pulsante, il servo continuerà a ruotare. Spero di averti dato qualche suggerimento utile!
Antonio ha detto:
ok gentilissimo…ci provo e ti aggiorno! 🙂
Antonio ha detto:
Ho provato quello sulla velocità, ma vorrei che ritornasse anche lento. come è scritto il codice dell’esempio il servo scende a passettini i poi risale a zero velocemente. come dovrei fare a farlo salire anche lentamente? grazie mille ancora
studioarduino ha detto:
Ciao Antonio! Per far muovere il servo lentamente anche al ritorno, è sufficiente utilizzare il codice dell’esempio e aggiungere, dopo il primo ciclo for, un secondo ciclo for che riporta il servo in posizione iniziale sempre a piccoli passi: il codice potrebbe essere scritto così: for (int n=90; n>0; n––) { …il resto è uguale… }. Buoni esperimenti!
Antonio ha detto:
Ci ho provato ma mi da errore…non riesco a capire cosa sbaglio. Lo so che chiedo molto, ma poichè sono alle prime armi spero in una sua comprensione. Potreste indicarmi dove inserire l’altro for? mi scuso ancora ma ho provato e non ci sono riuscito. grazie per la gentile pazienza
Antonio ha detto:
#include
Servo myservo; // Crea l’oggetto servo
int velocita = 0; // Inserite un valore da 0 a 100 (da lento a veloce)
void setup()
{
myservo.attach(9); // Attacca l’oggetto servo al pin 9
myservo.writeMicroseconds(1500); // Imposto il servo al centro
}
void loop()
{
for (int n=0; n<90; n++)
{
myservo.write(n); // Faccio muovere il servo di un grado
delay(calcolaVelocita()); // Imposto il ritardo prima del movimento successivo
}
delay(1000); // Attendo, prima di ricominciare da capo
}
int calcolaVelocita()
{
// Calcolo un ritardo da 120 a 20 ms al variare di velocita da 0 a 100.
return (map(velocita,0,100,120,20));
}
studioarduino ha detto:
Prova così:
void loop()
{
for (int n=0; n<90; n++)
{
myservo.write(n); // Faccio muovere il servo di un grado
delay(calcolaVelocita()); // Imposto il ritardo prima del movimento successivo
}
delay(1000); // Attendo, prima di ricominciare da capo
}
for (int n=90; n>0; n–)
{
myservo.write(n); // Faccio muovere il servo di un grado, in direzione opposta
delay(calcolaVelocita()); // Imposto il ritardo prima del movimento successivo
}
delay(1000); // Attendo, prima di ricominciare da capo
}
Non l'ho testato, ma dovrebbe funzionare! PS: la formattazione forse non è chiara, ma c’è scritto: n meno meno.
Antonio ha detto:
Purtroppo nella riga corrispondente al nuovo for mi da errore (stray ‘\’ in program
studioarduino ha detto:
Probabilmente è solo un errore di battitura. Prova a scrivere il codice, non fare copia e incolla. Controlla anche che non ci siano caratteri o spazi strani, e che nel secondo ciclo for ci sia scritto: n meno meno!
Antonio ha detto:
ok lo riscrivo e ti aggiorno. grazieeeeeeeeee
Antonio ha detto:
#include
Servo myservo; // Crea l’oggetto servo
int Velocita = 0; // Inserite un valore da 0 a 100 (da lento a veloce)
void setup()
{
myservo.attach(9); // Attacca l’oggetto servo al pin 9
myservo.writeMicroseconds(1500); // Imposto il servo al centro
}
void loop()
{
for (int n=0; n90; n–)
{
myservo.write(n);
delay(calcolaVelocita());
}
delay(100);
}
ORA MI DICE: MAYSERVO WAS NOT DECLARETED IN THIS SCOPE
studioarduino ha detto:
Ti sei ricordato di includere la libreria Servo.h all’inizio del file?
Antonio ha detto:
problema di battitura risolto. Ora mi dice: WAS NOT DECLARETED IN THIS SCOPE
studioarduino ha detto:
Controlla di avere incluso la libreria per controllare il servo. Riguarda il codice dell’esempio:
include
Antonio ha detto:
niente da fare! continua a darmi errore: calcolaVelocità WAS NOT DECLARETED IN THIS SCOPE
studioarduino ha detto:
Se il codice è quello che hai postato prima, manca la dichiarazione della funzione: per questo viene segnalato l’errore. Aggiungi la parte di codice in cui c’è scritto:
function calcolaVelocita() { ecc. } 🙂
Antonio ha detto:
Salve, ho dovuto abbandonare il progetto per dei problemi ma ora che ho ripreso non riesco ancora a farlo partire. Saresti così gentile da incollarmelo qui per intero? mi scuso e ti ringrazio mille per il tuo tempo e la tua disponibilità.
stefano ha detto:
Salve antonio volevo ringraziarti per questi tutorial estremamente efficaci. Volevo chiederti e se volessi muovere il servo con un potenziometro, facendo in modo che dopo la movimentazione del potenziometro la posizione del servo rimanga quella attuale e non ritorna alla posizione zero. Come faresti?