Robotica educativa/Joystick
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
modificaIl 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.
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
modificaAlimentando 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
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.
Codice
modificaDi 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
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
modificaDi 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- 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.