.. note:: 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 [|link_sf_facebook|] e unisciti oggi stesso! .. _2.1.6_c_mcp3008: 2.1.6 Joystick (MCP3008) ========================== .. note:: .. image:: img/mcp3008_and_adc0834.jpg :width: 25% :align: left 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. .. image:: img/image317-copy.png 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. .. image:: img/image318.png 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. .. .. image:: img/image319.png * - Nome T-Board - fisico - WiringPi - BCM * - SPICE0 - pin24 - 10 - 8 * - SPIMOSI - pin19 - 12 - 10 * - SPIMISO - pin21 - 13 - 9 * - SPISCLK - pin23 - 14 - 11 * - GPIO22 - pin15 - 3 - 22 .. image:: img/schematic_2.1.9_joystick_mcp3008.png Procedura sperimentale ----------------------- **Passo 1:** Monta il circuito. .. image:: img/july24_2.1.9_joystick_mcp3008.png Per utenti C ^^^^^^^^^^^^ **Passo 2:** Vai alla cartella del codice. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/2.1.6-2/ **Passo 3:** Compila il codice. .. raw:: html .. code-block:: gcc 2.1.6_Joystick.c -o joystick -lwiringPi **Passo 4:** Esegui il file eseguibile. .. raw:: html .. code-block:: ./joystick Dopo aver eseguito il codice, muovi il joystick: i valori corrispondenti di x, y e Btn saranno visualizzati sullo schermo. .. note:: Se non funziona dopo l’esecuzione o compare l’errore «wiringPi.h: No such file or directory», fai riferimento a :ref:`install_wiringpi`. **Codice** .. code-block:: c #include #include #include #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** 1. Questa sezione inizializza le librerie necessarie per la comunicazione GPIO e SPI. .. code-block:: c #include #include #include #define SPI_CHANNEL 0 #define SPI_SPEED 1000000 // 1 MHz #define BtnPin 3 // WiringPi 3 = BCM GPIO22 2. 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. .. code-block:: c 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; } 3. La funzione ``main`` inizializza WiringPi e SPI, configura il pin del pulsante del joystick e legge continuamente i valori, stampandoli sul terminale. .. code-block:: c 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 :ref:`spi_configuration` per le istruzioni dettagliate). Se hai già completato questi passaggi, puoi saltarli. **Passo 3:** Vai alla cartella del codice. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Passo 4:** Esegui. .. raw:: html .. code-block:: 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. .. warning:: Se compare l’errore ``RuntimeError: Cannot determine SOC peripheral base address``, fai riferimento a :ref:`faq_soc` **Codice** .. note:: 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. .. raw:: html .. code-block:: python #!/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** .. code-block:: python #!/usr/bin/env python3 import RPi.GPIO as GPIO import spidev import time Questa sezione importa le librerie necessarie: - ``RPi.GPIO`` per gestire l’input GPIO (pulsante del joystick). - ``spidev`` per comunicare con il chip MCP3008 tramite SPI. - ``time`` per inserire ritardi tra le letture. .. code-block:: python 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. .. code-block:: python 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. .. code-block:: python 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.