Nota
Ciao, benvenuto nella Community Facebook degli appassionati di SunFounder Raspberry Pi & Arduino & ESP32! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.
Perché unirti?
Supporto esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team.
Impara e condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.
Anteprime esclusive: Accedi in anteprima ai nuovi annunci di prodotto e agli sneak peek.
Sconti speciali: Godi di sconti esclusivi sui nostri prodotti più recenti.
Promozioni e giveaway festivi: Partecipa a concorsi e promozioni festive.
👉 Pronto a esplorare e creare con noi? Clicca [Qui] e unisciti oggi stesso!
2.1.6 Joystick (MCP3008)
Nota
A seconda della versione del tuo kit, identifica se hai ADC0834 o MCP3008 e segui la sezione corrispondente.
Introduzione
In questo progetto impareremo come funziona un joystick. Muoviamo il joystick e visualizziamo i risultati sullo schermo.
Componenti necessari
In questo progetto utilizziamo i seguenti componenti.
Principio
Joystick
Il concetto di base di un joystick è tradurre il movimento di una leva in informazioni elettroniche che un computer può elaborare.
Per comunicare l’intera gamma di movimenti al computer, un joystick deve misurare la posizione della leva su due assi: l’asse X (da sinistra a destra) e l’asse Y (dal basso verso l’alto). Come nella geometria di base, le coordinate X-Y individuano esattamente la posizione della leva.
Per determinare la posizione della leva, il sistema di controllo del joystick monitora semplicemente la posizione di ciascun asse. Il design convenzionale del joystick analogico lo fa utilizzando due potenziometri, o resistori variabili.
Il joystick ha anche un ingresso digitale che si attiva quando viene premuto verso il basso.
Schema elettrico
Quando si leggono i dati del joystick, ci sono alcune differenze tra gli assi: i dati degli assi X e Y sono analogici, quindi è necessario usare MCP3008 per convertirli in valori digitali. I dati dell’asse Z sono digitali, quindi puoi leggerli direttamente tramite GPIO o anche tramite ADC.
Procedura sperimentale
Passo 1: Monta il circuito.
Per utenti C
Passo 2: Vai alla cartella del codice.
cd ~/davinci-kit-for-raspberry-pi/c/2.1.6-2/
Passo 3: Compila il codice.
gcc 2.1.6_Joystick.c -o joystick -lwiringPi
Passo 4: Esegui il file eseguibile.
./joystick
Dopo aver eseguito il codice, muovi il joystick: i valori corrispondenti di x, y e Btn saranno visualizzati sullo schermo.
Nota
Se non funziona dopo l’esecuzione o compare l’errore «wiringPi.h: No such file or directory», fai riferimento a Installare e Verificare WiringPi.
Codice
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#define SPI_CHANNEL 0
#define SPI_SPEED 1000000 // 1 MHz
#define BtnPin 3 // WiringPi 3 = BCM GPIO22
// Lettura dal canale MCP3008 (0–7)
int read_ADC(int channel) {
if (channel < 0 || channel > 7) return -1;
unsigned char buffer[3];
buffer[0] = 1; // Bit di avvio
buffer[1] = (8 + channel) << 4; // Configurazione canale
buffer[2] = 0;
wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
int result = ((buffer[1] & 0x03) << 8) | buffer[2];
return result;
}
int main(void) {
if (wiringPiSetup() == -1) {
printf("Inizializzazione WiringPi fallita!\n");
return 1;
}
if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
printf("Configurazione SPI fallita!\n");
return 1;
}
pinMode(BtnPin, INPUT);
pullUpDnControl(BtnPin, PUD_UP);
while (1) {
int x_val = read_ADC(0); // VRX su CH0
int y_val = read_ADC(1); // VRY su CH1
int btn_val = digitalRead(BtnPin); // Pulsante SW
printf("x = %d, y = %d, btn = %d\n", x_val, y_val, btn_val);
delay(100);
}
return 0;
}
Spiegazione del codice
Questa sezione inizializza le librerie necessarie per la comunicazione GPIO e SPI.
#include <wiringPi.h> #include <wiringPiSPI.h> #include <stdio.h> #define SPI_CHANNEL 0 #define SPI_SPEED 1000000 // 1 MHz #define BtnPin 3 // WiringPi 3 = BCM GPIO22
Definisce la funzione
read_ADC()per leggere i dati analogici dal MCP3008. Comunica via SPI per richiedere dati da un canale (0–7) e interpreta la risposta per ottenere un valore ADC a 10 bit.int read_ADC(int channel) { if (channel < 0 || channel > 7) return -1; unsigned char buffer[3]; buffer[0] = 1; buffer[1] = (8 + channel) << 4; buffer[2] = 0; wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3); int result = ((buffer[1] & 0x03) << 8) | buffer[2]; return result; }
La funzione
maininizializza WiringPi e SPI, configura il pin del pulsante del joystick e legge continuamente i valori, stampandoli sul terminale.int main(void) { if (wiringPiSetup() == -1) { printf("Inizializzazione WiringPi fallita!\n"); return 1; } if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) { printf("Configurazione SPI fallita!\n"); return 1; } pinMode(BtnPin, INPUT); pullUpDnControl(BtnPin, PUD_UP); while (1) { int x_val = read_ADC(0); // VRX su CH0 int y_val = read_ADC(1); // VRY su CH1 int btn_val = digitalRead(BtnPin); // SW su GPIO22 printf("x = %d, y = %d, btn = %d\n", x_val, y_val, btn_val); delay(100); } return 0; }
Per utenti Python
Passo 2: Configura l’interfaccia SPI e installa la libreria spidev (vedi Configurazione SPI per le istruzioni dettagliate). Se hai già completato questi passaggi, puoi saltarli.
Passo 3: Vai alla cartella del codice.
cd ~/davinci-kit-for-raspberry-pi/python
Passo 4: Esegui.
sudo python3 2.1.6-2_Joystick.py
Dopo aver eseguito il codice, muovi il joystick: i valori corrispondenti di x, y e Btn saranno visualizzati sullo schermo.
Avvertimento
Se compare l’errore RuntimeError: Cannot determine SOC peripheral base address, fai riferimento a Se gpiozero non funziona.
Codice
Nota
Puoi Modificare/Reimpostare/Copiare/Eseguire/Fermare il codice qui sotto. Prima di farlo, vai nella cartella del codice sorgente come davinci-kit-for-raspberry-pi/python. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
# Pin GPIO per il pulsante del joystick (SW)
BTN_PIN = 22
# Configurazione GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Pull-up interno
# Inizializzazione SPI con MCP3008
spi = spidev.SpiDev()
spi.open(0, 0) # Bus SPI 0, CE0
spi.max_speed_hz = 1000000 # 1 MHz
def read_adc(channel):
"""
Legge il valore analogico dal canale MCP3008 specificato (0–7)
:param channel: numero canale ADC (0–7)
:return: valore intero a 10 bit (0–1023)
"""
if channel < 0 or channel > 7:
return -1
adc = spi.xfer2([1, (8 + channel) << 4, 0])
value = ((adc[1] & 0x03) << 8) | adc[2]
return value
try:
# Ciclo principale: legge e stampa i valori del joystick e lo stato del pulsante
while True:
x_val = read_adc(1) # VRX collegato a CH1
y_val = read_adc(2) # VRY collegato a CH2
Btn_val = GPIO.input(BTN_PIN) # 0 = premuto, 1 = rilasciato
print('X: %d Y: %d Btn: %d' % (x_val, y_val, Btn_val))
time.sleep(0.2)
except KeyboardInterrupt:
pass
finally:
spi.close()
GPIO.cleanup()
Spiegazione del codice
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
Questa sezione importa le librerie necessarie:
RPi.GPIOper gestire l’input GPIO (pulsante del joystick).spidevper comunicare con il chip MCP3008 tramite SPI.timeper inserire ritardi tra le letture.
BTN_PIN = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000
Questo blocco imposta la modalità GPIO su BCM, inizializza l’input del pulsante su GPIO22 con resistenza pull-up interna e configura l’interfaccia SPI con MCP3008 usando bus 0 e CE0 a 1 MHz.
def read_adc(channel):
if channel < 0 or channel > 7:
return -1
adc = spi.xfer2([1, (8 + channel) << 4, 0])
value = ((adc[1] & 0x03) << 8) | adc[2]
return value
Definisce la funzione read_adc() per leggere i dati analogici da un canale MCP3008 specifico, inviando tre byte via SPI e interpretando la risposta come valore a 10 bit.
try:
while True:
x_val = read_adc(0)
y_val = read_adc(1)
Btn_val = GPIO.input(BTN_PIN)
print('X: %d Y: %d Btn: %d' % (x_val, y_val, Btn_val))
time.sleep(0.2)
except KeyboardInterrupt:
pass
finally:
spi.close()
GPIO.cleanup()
Il ciclo principale legge e stampa le posizioni X/Y e lo stato del pulsante ogni 200 ms. Se il programma viene interrotto (Ctrl+C), SPI e GPIO vengono chiusi correttamente.