Vai al contenuto

Robotica educativa/Joystick

Wikibooks, manuali e libri di testo liberi.
Indice del libro

Il tanto amato joystick. Chi afferma di non conoscerlo sicuramente sta mentendo. Nato nel mondo dei videogiochi ora è utilizzato in ogni ambito, fino a quello biomedicale, incluse operazioni delicatissime che non potrebbero essere svolte manualmente. Ecco perché è così importante.

Quest'immagine serve solo a ingolosire chi legge. Il joystick di Arduino è molto più piccolo, è pensato per essere manovrato da un singolo pollice, pertanto: perché accontentarsi di uno solo?

Procedendo per gradi è interessante ispezionare il suo circuito interno, così da capire come funziona e cosa si può ottenere da un dispositivo così semplice.

Dentro il joystick

[modifica | modifica sorgente]

Il joystick di Arduino non è diverso da quelli visti nelle sale giochi o scavando nei ricordi d'infanzia. Dispone di tre possibili comandi:

  • una movimentazione orizzontale;
  • una movimentazione verticale;
  • la pressione (associabile a un comando).

Va detto che la movimentazione non è semplicemente alto/basso, sinistra/destra, ma restituisce un valore proporzionale all'angolo con cui si sta premendo il joystick. Naturalmente, se la pressione è in diagonale, viene restituita sia la proiezione sull'asse delle ascisse, sia quella sull'asse delle ordinate della sua movimentazione.

Schema elettrico del Joystick per Arduino
Schema elettrico del joystick per Arduino

Infatti la movimentazione del joystick scivola (in orizzontale e in verticale) su due resistenze variabili da , restituendo così una tensione compresa tra e la quale, connessa ai pin analogici, viene campionata a 10 bit, restituendo un numero compreso tra 0 e 1023 (), mentre – a riposo, se correttamente calibrato – dovrebbe restituire 511 ().

Pertanto, il joystick non rivela soltanto se la pressione è verso l'alto o verso il basso, ma anche di quanto. Analogamente questo accade per la movimentazione a sinistra e a destra.

La pressione del joystick chiude l'interruttore che si porta a livello basso.

Tutte queste premesse per dire che il controllo del joystick può avvenire senza l'ausilio di nessuna libreria.

Calibrazione

[modifica | modifica sorgente]

Alimentando il joystick con la tensione fornita da Arduino e prelevandone una porzione, grazie ai due potenziometri, il valore atteso per la situazione di riposo è 511. Tuttavia non è detto che sia sempre così. I componenti elettrici ed elettronici non sono perfetti, e le resistenze hanno un valore che dipende, oltre che dalle loro componenti intrinseche, anche dalla temperatura.

Se si desidera semplicemente sapere se il movimento è verso l'alto, il basso, a sinistra o a destra, quello che segue non è rilevante. Tuttavia, se si desidera utilizzare il joystick come strumento di lavoro è bene conoscere almeno tre parametri:

  • valore minimo (quando è completamente in basso o a sinistra);
  • valore a riposo (senza interazioni con l'utente);
  • valore massimo (quando è completamente in alto o a destra).

Nota bene

Come anticipato, questa operazione va eseguita inizialmente, soprattutto se si desidera acquisire, oltre alla direzione dettata dall'orientamento del joystick, anche il suo valore.

A titolo di esempio, se si vuole pilotare un motore e, tramite il joystick, definire oltre al verso di rotazione (avanti/indietro) la sua velocità è bene procedere a una taratura iniziale.

Questa va fatta per ogni componente, poiché ogni joystick restituirà dati differenti.

Come visibile dallo schema elettrico le tensioni e dipendono da due diverse resistenze. Per quanto il costruttore abbia fatto tutto il possibile affinché queste siano identiche, è risaputo che non esistono due oggetti identici in natura.

La calibrazione avviene con un codice che deve semplicemente mostrare i valori e nel monitor seriale. Nel codice che segue viene testato anche il funzionamento del pulsante.

// Terminali a cui va connesso il joystick
#define VRx A0
#define VRy A1
#define SW   2

// Dati restituiti dal joystick
int x, y, pulsante;
 
void setup() {
    Serial.begin(9600);
    pinMode(pulsante, INPUT);
}
 
void loop() {
    // Legge i dati del joystick
    x = analogRead(VRx);
    y = analogRead(VRy);
    pulsante = digitalRead(SW);
 
    // Li mostra nel monitor seriale
    Serial.print("VRx: ");
    Serial.print(x);
    Serial.print(" | VRy: ");
    Serial.print(y);
    Serial.print(" | Button: ");
    Serial.println(pulsante);
 
    // Attende 100 ms
    delay(100);
}

È fondamentale acquisire i dati minimi, massimi e a riposo. In tabella viene riportato un esempio:

Elemento Valore

minimo

Valore

a riposo

Valore

massimo

0 523 1023
0 498 1023

Si noti che, tipicamente, i valori a riposo difficilmente coincideranno con 511. Una volta acquisiti questi dati si è pronti per calibrare il joystick.

Ora che si dispone di questi dati è possibile correggere i dati x e y con i dati ottenuti durante la calibrazione.

Di seguito il codice per l'acquisizione dei dati del joystick ricalibrati con i dati ottenuti.

// Valori ottenuti in sede di calibrazione
#define xMin 0
#define xMid 523
#define xMax 1023
#define yMin 0
#define yMid 498
#define yMax 1023

// Terminali a cui va connesso il joystick
#define VRx A0
#define VRy A1
#define SW   2

// Dati restituiti dal joystick
int x, y, pulsante;

// Dati restituiti dal joystick e corretti
int x1, y1;

void setup() {
    Serial.begin(9600);
    pinMode(pulsante, INPUT);
}

void loop() {
    int x = analogRead(VRx);
    int y = analogRead(VRy);

    // Rettifica i dati forniti dal joystick
    joystick();

    // Li mostra nel monitor seriale
    Serial.print("VRx: ");
    Serial.print(x1);
    Serial.print(" | VRy: ");
    Serial.print(y1);
    Serial.print(" | Button: ");
    Serial.println(pulsante);

    // Attende 100 ms
    delay(100);
}

// Dai dati grezzi x, y del joystick restituisce i dati calibrati x1 e y1
void joystick() {
    if (x < xMid)
        x1 = map(x, xMin, xMid, 0, 511);
    else
        x1 = map(x, xMid, xMax, 512, 1023);
    
    if (y < yMid)
        y1 = map(y, yMin, yMid, 0, 511);
    else
        y1 = map(y, yMid, yMax, 512, 1023);
}

Si noti che nella funzione joystic() si è utilizzata la funzione map. Per chi non l'avesse mai usata , essa – data una variabile compresa tra un valore minimo e massimo – restituisce una sua rimappatura rispetto a due altri termini (anch'essi minimo e massimo).

Matematicamente, si scrive:

Attenzione

La funzione map() utilizza e restituisce numeri interi.

In questo caso è quello che si vuole, ma frazioni come , , saranno tutte restituite come 1 dalla funzione map(), nonostante i loro valori reali siano differenti.

Pertanto, se il progetto richiede calcoli precisi (come valori con una o più cifre decimali), è bene evitare map() e implementare la funzione manualmente come descritto nell'equazione precedente.

Schema circuitale

[modifica | modifica sorgente]

Di seguito come collegare il joystick ad Arduino:

Sin qui tutto bene. Ora si ha a disposizione un joystick (perfettamente calibrato) e connesso ad Arduino. Naturalmente, si può controllare qualsiasi dispositivo. Di più: nulla vieta di inserire più di un joystick. Arduino Uno, avendo sei ingressi analogici ne può ospitare fino a tre.

Espansioni suggerite

[modifica | modifica sorgente]
  • La cosa più semplice è inserire quattro led che mostrano la direzione in cui è orientato il joystick (volendo un quinto potrebbe mostrare se il joystick è premuto o meno). Senza modificare il circuito, se le uscite sono analogiche la pressione del joystick può essere resa visibile con l'intensità luminosa dei led stessi.
  • I led possono essere sostituiti con motori. Utilizzando fili un po' più lunghi si può comandare un robot. Questo, naturalmente, può anche essere telecomandato se si utilizza un sistema di trasmissione e ricezione.
  • Con matrici di led (es. 8x8) è possibile realizzare semplici videogiochi come snake.