I servo motori sono una particolare tipologia di motore, che grazie alle loro caratteristiche e semplicità di uso, vengono spesso utilizzati nei primi esempi di controllo motori su schede come Arduino o Raspberry. Il modellismo fa molto uso di questa tipologia di motori e sono disponibili sul mercato moltissimi servo motori a basso costo, utili anche per scopi didattici. In questo articolo vedremo dapprima cosa sono i servo motori, come utilizzarli ed infine come programmare Arduino per poterli utilizzare con alcuni semplici esempi.
Cosa è un Servo Motore
Un servo motore ha la peculiarità di impostare il perno di trasmissione della rotazione su angoli esatti compresi in un certo intervallo, che spesso vanno da 0 a 180°, ma ve ne sono anche di modelli che coprono intervalli maggiori.
Il poter disporre di un motore che regoli la rotazione di un asse per fargli assumere un preciso angolo desiderato è utile in moltissime applicazioni. Basti pensare al semplice modellismo, in cui vogliamo utilizzare questo motore per regolare la rotazione di un timone per una nave o un aeroplanino, oppure quella di un volante per far sterzare le ruote con un determinato angolo.
Altre applicazioni possibili possono essere quelle in robotica, quando si desidera far assumere a determinati componenti delle particolari angolazioni una con l’altra.
Per ottenere questo particolare movimento, si deve analizzare in dettaglio come è composto all’interno un servo motore. La rotazione del perno in uscita si ottiene attraverso un motore DC (a corrente continua) collegato ad un meccanismo di demoltiplica che consente di aumentare la coppia in fase di rotazione, riducendo la velocità e aumentando la forza di torsione.
Per quanto riguarda il controllo dell’angolo di rotazione, questo viene attuato attraverso un circuito di controllo interno che grazie ad un potenziometro resistivo riesce a conoscere l’angolo di rotazione del perno. Una volta raggiunto l’angolo desiderato, il circuito di controllo blocca il motore.
Grazie a questo meccanismo, i servo motori sono in grado di garantire un controllo molto preciso sul grado di rotazione del suo perno.
Come funzionano i servo motori
Un servo motore controlla la rotazione di un motore DC attraverso un circuito di controllo che ne regola l’angolo. Il controllo viene ottenuto regolando la lunghezza di un impulso ad onda quadra inviato al servo motore. La lunghezza dell’impulso in un treno di segnali si definisce tramite il PMW (Pulse Modulation Width).
Questo treno di impulsi si caratterizza dal duty cycle, cioè dal tempo occupato dall’impulso rispetto all’interno periodo destinato ad un singolo segnale. Per esempio, la classica onda quadra ha un duty cycle del 50%, dato che la durata dell’impulso (parte del segnale con stato 1) è pari alla metà del periodo dell’onda (cioè pari a quella parte del segnale con stato 0).
Ma si possono avere altri treni di impulsi con duty cycle diversi. Se infatti riduciamo la durata dello stato 1 del segnale, ridurremo il duty cycle.
Oppure si può fare l’opposto, incrementando il periodo, per ottenere duty cycle maggiori.
Modulando quindi quindi queste durate durante l’invio di un treno di impulsi si possono inviare delle informazioni al sistema di controllo nel servo motore. A seconda del duty cycle, varierà l’angolo di rotazione. Partendo da un duty cycle del 1%, corrispondente all’angolo di 0°, via via incrementando il duty cycle, crescerà anche l’angolo di rotazione del servo motore. Con un duty cycle del 50%, il perno del motore si posizionerà su 90° (che è proprio la metà dell’intervallo di rotazione possibile). Con un duty cycle del 99%, avremo una rotazione di 180°.
Quindi, attraverso questo sistema di modulazione PMW, saremo in grado di inviare dei comandi dall’esterno al servo motore per fargli assumere l’angolo di rotazione desiderato.
Arduino e PMW
Arduino è in grado di generare dei PMW in maniera molto semplice. Per quanto riguarda i vari PIN, si possono avere due diverse frequenze di emissione di PMW.
Per utilizzare in maniera semplice ed intuitiva i servo motori, e generare le PMW con il duty cycle desiderato, Arduino IDE include al suo interno una libreria specifica, chiamata Servo. Per poterla includere all’interno dello sketch, è sufficiente aggiungere all’inizio.
#include <Servo.h>
Assembliamo Arduino con il servo motore
Molti dei servo motori per modellismo disponibili in commercio funzionano a 5V, e quindi si possono connettere direttamente all’alimentazione del PIN 5V fornita da Arduino. Ma per garantire una maggiore sicurezza della scheda (e della porta USB collegata al computer) sarebbe meglio aggiungere un’alimentazione esterna.
Nel mio esempio ho utilizzato un servo motore Hi-Tec SERVO HS-485HB
Quindi nel mio caso ho preferito aggiungere un modulo vano per alimentazione a 4 pile stilo AA come sorgente di alimentazione.
Come potete vedere, ho connesso il PIN 5V ed il PIN GND di Arduino all’alimentazione esterna, questo ci permette di alimentare, oltre che il servo motore anche la scheda Arduino. Infatti una volta scaricato lo sketch compilato nella scheda Arduino, potrete staccare la porta USB, e Arduino continuerà a funzionare alimentato dalle batterie.
Ma attenzione, è un collegamento particolare e piuttosto rischioso per la scheda Arduino, se non si comprende quello che si fa e non si seguono particolari accortezze. A tal riguardo aggiungo un paragrafo di approfondimento al riguardo.
Alimentazione con Collegamento diretto al Pin 5V
E’ possibile collegare una tensione stabilizzata direttamente al PIN 5V di Arduino per poterlo alimentare (insieme alla massa sul PIN GND). La tensione applicata dovrà essere assolutamente tra i 4.5V ed i 5.5V. Non essendoci alcun tipo di protezione, qualsiasi valore superiore porterebbe alla bruciatura irreversibile della scheda. Un voltaggio inferiore al suo non funzionamento corretto. Anche l’inversione accidentale dei cavi, tra positivo e negativo, porterebbe alla distruzione della scheda.
Un aspetto positivo è invece quello di non dover più tener sotto controllo il regolatore di tensione per eventuali surriscaldamenti, dato che non viene più utilizzato.
Quindi come nel caso in questione, quando si ha bisogno di lavorare con dispositivi aggiuntivi che richiedono 5V, questa connessione potrebbe risulatere ideale, come appunto i servomotori.
Per quanto riguarda la sorgente di alimentazione, la migliore soluzione è quella di utilizzare un modulo a 4 battere stilo ricaricabili in serie, ognuna delle quali ha una tensione nominale di 1.25V, e quindi potranno generare una tensione di 5.0V. Fate attenzione invece alle batterie stilo normali (che dovrebbero avere una tensione nominale parti a 1.5V). Infatti quest’ultime forniscono voltaggi pari a 6V, tensione troppo alta per essere supportata da Arduino.
Quindi, la soluzione è quella di utilizzare solo Battterie Stilo Ricaricabili KR6 (NiCd) o HR6 (NiMH). Se non siete sicuri, prima di utilizzare le batterie in serie, misuratene la tensione con un voltmetro.
Programmiamo Arduino
Adesso, una volta eseguiti tutti i collegamenti, apriamo Arduino IDE e cominciamo a scrivere due semplici esempi, che ci permetteranno di comprendere i comandi basilari della libreria Servo, e vedere come funzionano i servo motori.
Definiamo l’angolo a 0°
Per prima cosa sarebbe utile poter marcare in qualche modo la posizione del perno corrispondente a 0°. Questa è molto utile per poi avvitarci i dischetti bianchi forati nella giusta posizione e regolarsi così di conseguenza sul possibile assetto dello spazio di movimento tra 0 e 180°.
Quindi facciamo uno sketch che ci imposti il servo motore sulla posizione corrispondente alla rotazione a 0°.
Apriamo Arduino IDE ed inseriamo il seguente sketch.
#include <Servo.h>
Servo servo1;
int servoPin = 9;
void setup(){
servo1.attach(servoPin);
}
void loop(){
servo1.write(0);
}
La prima riga di codice importa la libreria che ci fornisce una serie di metodi e funzioni che ci facilitano il controllo di uno più servo motori. Una volta importata la libreria la prima cosa da fare è quella di creare un oggetto corrispondente al servo motore che utilzzeremo per tutto il codice. Si possono infatti utilizzare diversi servo motori e specificare in modo univoco ciascuno di essi. Quindi chiameremo servo1 il servo motore del nostro esempio.
All’interno del blocco setup() dello sketch, inseriremo la funzione attach() che definirà su quale pin è connesso il servo motore, servoPin.
servo1.attach(servoPin);
Nel blocco loop() invece inseriremo la funzione write(), sempre riferita al nostro motore servo1.
servo1.write(angle);
L’angolo specificato come parametro dovrebbe essere espresso in gradi con un range compreso tra 0 e 180 gradi. L’angolo specificato modula la durata dell’impulso inviato al servo motore tramite PMW. Quest’ultimo si sposterà nella posizione corrispondente. Quindi per far girare il perno nella posizione a 0°, si scriverà:
servo1.write(0);
Compiliamo ed carichiamo lo sketch su Arduino. Il servo motore si muoverà nella posizione corrispondente a 0°. A questo punto, con un marker bianco segnate la posizione di riferimento. Da questo punto in poi potrete montare e smontare i dischetti forati, e altri accessori utilizzando questo segno come punto di riferimento.
Muoviamo il Servo motore su tutto il range di angoli da 0 a 180 gradi
Adesso che abbiamo visto le funzioni essenziali per inviare gli angoli al servo motore su cui posizionarsi, vediamo un esempio un po’ più completo, in cui faremo girare il servo motore gradualmente coprendo tutto l’intervallo di rotazione.
Copiate il seguente sketch su Arduino IDE
#include <Servo.h>
Servo servo1;
int servoPin = 9;
void setup(){
Serial.begin(9600);
servo1.attach(servoPin);
}
void loop(){
for(int i=0; i < 180; i++){
servo1.write(i);
delay(500);
Serial.print("Angle: ");
Serial.print(i);
Serial.println(" degrees");
}
}
Abbiamo inserito un ciclo FOR nel blocco loop(), in modo da iterare tra 0 e 180 gradi in modo graduale, grado per grado. Il comando write() sposterà il servo motore di un grado per ogni iterazione. Alla fine del ciclo, il servo motore raggiungerà i 180° e poi ripartirà da 0°.
Rispetto all’esempio precedente, abbiamo creato una comunicazione seriale in modo da monitorare l’andamento della rotazione del motore, inviando sul Serial Monitor di Arduino IDE l’angolo corrente di posizione del servo motore.
Compilando e caricando lo sketch su Arduino, e dopo aver avviato il Serial Monitor vedremo il servo motore muoversi molto molto lentamente, quasi impercettibilmente. Sul monitor invece verranno visualizzate in tempo reale tutte le posizioni correnti del servo motore.
La funzione SERVO.writeMicroseconds()
Il comando servo.write(angle) lavora per la maggior parte dei servo motori ma non per tutti. Alcuni servo motori hanno un range di 180 gradi, altri un range di 90 gradi e alcuni una via di mezzo. Usando il comando servo.write(angle) permette un massimo di 180 step. Comunque, esiste un comando che permette fino a 1000 step: servo.writeMicroseconds(). Per la maggior parte delle applicazioni, il semplice servo.write(angle) lavorerà bene. Ma se vuoi un controllo più preciso, avrai bisogno di usare servo.writeMicroseconds().
Modifichiamo quindi il codice sketch precedente per poter utilizzare questa funzione. Controllando le specifiche del servo motore utilizzato e sapendo che la frequenza di PMW del PIN 9 su Arduino è di 488Hz. Avremo un treno di impulsi con periodo di 2000 us. In questo caso non avremo più la traduzione in gradi angolo, e quindi dovremo effettuare diverse prove per calibrare la lunghezza in microsecondi degli impulsi con l’angolo di rotazione.
Questo esempio, grazie al perno del servo motore contrassegnato a 0°, di poter in qualche modo tradurre la durata dell’impulso (o percentuale del duty cycle) con l’angolo di rotazione del nostro servo motore (questo cambierà di modello in modello).
#include <Servo.h>
Servo servo1;
int servoPin = 9;
void setup(){
Serial.begin(9600);
servo1.attach(servoPin);
}
void loop(){
for(int i=60; i < 200; i++ ){
int t = i*10;
int angle = map(t, 600, 2000, 0, 180);
servo1.writeMicroseconds(t);
delay(500);
Serial.print("Angle: ");
Serial.print(angle);
Serial.print(" degrees. (");
Serial.print(t);
Serial.println("uS)");
}
}
Nel mio caso ho fatto ruotare il mio servo motore partendo da 600 us fino al valore massimo di 2000 us, che su Arduino equivale ad un duty cycle del 100%. Per aumentare la velocità ho fatto iterare nel ciclo FOR, i tempi a 10 us per iterazione.
for(int i=60; i < 200; i++ ){
int t = i*10;
Anche in questo caso, utilizzerò il Monitor seriale per seguire l’andamento della rotazione e vedere (e ricorreggere) il valore dei gradi corrispondenti alle varie durate degli impulsi.