GLG Programs fa uso di cookie per migliorare l'esperienza di navigazione degli utenti, ma non per tracciarne un profilo. Proseguendo nella navigazione, si accetta implicitamente l'utilizzo dei cookie.
[OK]Note legaliNon mi importa
Logo GLGPrograms Logo GLGPrograms

Dispense Arduino

[Icona della Guida] Materiale tratto dal nostro corso di base Arduino, con esempi ed esercizi

Impulsi, LED variabili e motori

Affrontiamo adesso l'argomento della generazione di impulsi variabili con Arduino, funzione nota come PWM; è una tecnica molto utilizzata perché produce effetti equiparabili ad un output analogico: la applicheremo infatti per variare la luminosità dei led o la velocità dei motori.

Nella seconda parte della pagina accenneremo ad alcuni tipi di motori ed ai metodi per pilotarli con Arduino.

Il PWM

Esempio di segnale PWM

PWM è l'acronimo di Pulse Width Modulation, ovvero modulazione a larghezza di impulso: questa è una funzionalità che possiedono alcuni piedini del microcontrollore, che consente di generare un'onda quadra a frequenza fissata, ma con un tempo ON solitamente diverso da quello OFF. Nell'immagine a lato, ad esempio, abbiamo un segnale con un periodo di 2ms, e quindi con una frequenza di 500Hz (). Il segnale è però alto solo per 1/3 del periodo, circa 0.67ms: la percentuale di tempo in cui il segnale è ON per ogni periodo prende il nome di duty cycle (ciclo utile), e in questo caso è circa 33%.

pin del PWM

Il PWM è generato in maniera asincrona rispetto al programma caricato, ed è gestito da componenti hardware (timer) che hanno un'uscita su soli 6 pin, contrassegnati da una tilde ~ o dalla sigla PWM.

Il primo esempio che vediamo riguarda il led dimming, andremo cioè a variare la luminosità di un LED alimentandolo con impulsi anziché con una tensione fissata. La minore luminosità è dovuta alla persistenza della visione dell'occhio, che non distingue il lampeggio del led, e ne percepisce una luminosità media continua.

Circuito PWM con LED
const byte PWMpin = 11;

void setup() {
   pinMode(PWMpin, OUTPUT);
}
void loop() {
   // Accensione
   for (byte dim = 0; dim < 255; dim++) {
     analogWrite(PWMpin, dim);
     delay(10);
   }

   // Spegnimento
   for (byte dim = 255; dim > 0; dim--) {
     analogWrite(PWMpin, dim);
     delay(10);
   }
}

Vediamo che il circuito non è variato molto dal più semplice esempio del led lampeggiante, tranne per il pin a cui è collegato, che adesso deve necessariamente essere abilitato all'output PWM.

Nel programma andiamo invece ad impostare il pin in output, per poi entrare nel loop. Qui incontriamo la funzione analogWrite(pin, duty), che si occupa della generazione del segnale PWM: il primo parametro pin è il pin su cui si va a fare l'output, 11 nel nostro caso; duty va invece ad impostare il duty cycle, la larghezza dell'impulso. Siccome i timer di Arduino sono ad 8-bit, dovrà essere un valore compreso fra 0 e 255.
È presente un ciclo for con cui si incrementa la variabile dim, ottenendo ad ogni giro un duty cycle maggiore. Siccome la variazione è pressoché istantanea (il clock di Arduino è a 16MHz, ogni operazione è eseguita in circa 70 nanosecondi) è inserita una pausa di 10 millisecondi nel ciclo, in questo modo il led si accenderà gradualmente in circa 2.5 secondi. Con il secondo for si esegue l'operazione simmetrica di spegnimento graduale.

Esercizi

Motori DC

Per uso hobbystico, a basse tensioni e correnti, si trovano sul mercato principalmente tre tipi di motori:

Per quanto riguarda la descrizione teorica dei motori DC rimando alla relativa pagina del sito, dove sono descritti in maniera più approfondita. L'unica discrepanza che si incontra riguarda l'esempio di collegamento con Arduino, dove si fa uso di un particolare tipo di transistor adatto a correnti più elevate. Vediamo qui un esempio con un generico BC546 al suo posto (transistor BJT NPN).

Circuito di motore DC con transistor Schema di motore DC con transistor
const byte POTENZ = A0; // potenziometro
const byte MOTORE = 9;  // motore

void setup() {
   // inizializza il motore come output
   pinMode(MOTORE, OUTPUT);
}

void loop(){
   byte valore = map(analogRead(POTENZ),0,1023,0,255);
   // il motore gira con velocità proporzionale alla
   // rotazione del potenziometro
   analogWrite(MOTORE,valore);
   delay(10);
}

La circuiteria è totalmente equivalente a quella descritta nella pagina dedicata, mentre il codice sorgente differisce in parte: abbiamo un potenziometro da cui leggiamo un valore, che viene però riproporzionato, utilizzando la funzione map, per essere ristretto in un intervallo 0~255 anziché 0~1023.
Così come per i LED, anche il motore può essere alimentato con un segnale PWM: anch'esso ha una determinata inerzia, e con un segnale impulsivo variabile possiamo variarne la velocità, senza perdere eccessivamente in coppia motrice: difatti per rallentarlo si potrebbe anche ridurne la tensione ai capi, ma ciò indebolisce i campi magnetici interni, e quindi la forza motrice.

Esercizi

Servomotori

Motore servo
Esempio di motore servo

Quando un progetto richiede una buona precisione nei movimenti si può ricorrere a svariate soluzioni: motori passo passo, uso di encoder su motori DC per poter conoscerne la posizione esatta, ma senza dubbio la soluzione più economica per piccole applicazioni è il motore servo.
In un parallelepipedo di plastica è integrato un motore DC provvisto di ingranaggi di riduzione, per aumentarne la coppia, un potenziometro che rileva la posizione dell'asse, ed una scheda elettronica che consente di pilotarlo con un singolo filo. Il range di movimenti è, solitamente, da 0 a 180°, anche se si possono trovare anche modelli che possono compiere un giro completo.

Il funzionamento interno, in linea di massima, non è molto complesso: il servo è pilotato con segnale PWM, che viene convertito in un segnale analogico con appositi filtri. Un comparatore interno confronta il segnale inviato con la lettura sul potenziometro interno, muovendo il motore se questi sono diversi. L'equilibrio si raggiunge quando l'asse raggiunge la posizione desiderata (un meccanismo elettronico di questo tipo è detto feedback negativo)

In realtà a noi non interessa molto il funzionamento interno, poiché Arduino integra una libreria che provvede automaticamente a generare un segnale PWM corrispondente ad un angolo specificato.

Circuito motore servo
#include <Servo.h>
Servo myservo;
void setup()
{
    myservo.attach(9);
}

// Libreria per i servo
// crea un oggetto Servo (myservo)
// setta il pin 9 al servo
void loop()
{
    for (byte posizione = 0; posizione < 180; posizione++) {
        myservo.write(posizione);
        // Muove il servo a zero
        delay(10);
    }
    delay(1000); // Pausa

    for (byte posizione = 178; posizione > 0; posizione--) {
        myservo.write(posizione);
        // Muove il servo a zero
        delay(10);
    }
    delay(1000); // Pausa
}

L'obiettivo dell'esempio è di far ruotare il motore dalla posizione 0° fino a 180°, per poi farlo tornare indietro dopo una pausa di un secondo.
Le connessioni elettroniche di un servo non richiedono l'uso di una breadboard, essendo molto semplici: è necessario solamente alimentarlo e collegare il morsetto di controllo ad Arduino, in questo caso il pin 9.

La prima riga del codice specifica che sarà necessario aggiungere alla compilazione anche la libreria Servo.h. Con questa è possibile creare un oggetto Servo: si tratta di una struttura dati tipica del C++ che agglomera un insieme di variabili e funzioni, nel nostro caso chiamata myservo. All'interno dell'oggetto sono nascoste, in questo caso, le istruzioni per il funzionamento del motore servo. Noi possiamo controllarlo senza dover mettere mano ai meccanismi precedemente descritti, semplicemente chiamando specifiche funzioni: vediamo nel setup attach(9), con cui si imposta il pin di Arduino destinato all'output verso il motore. Nel loop invece si richiama write(passi), settando con un valore compreso fra 0 e 179 la posizione del servo. Sarà la funzione poi a convertirlo nell'adeguato valore di PWM da generare sul pin di output.

La variazione di posizione del motore non è istantanea, pertanto è necessario inserire una piccola pausa fra un movimento e l'altro. Riducendone il tempo, la funzione write(passi) viene chiamata con frequenza maggiore, pertanto il motore si muoverà più rapidamente.

Esercizi

Pagina scritta da GiulioGiulio

Hai una domanda? Scrivici!
Questa pagina ti è piaciuta? Condividila!
Share on Facebook Share on Google+ Share on linkedin