.. note::
Hallo und willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauche tiefer in Raspberry Pi, Arduino und ESP32 mit anderen Enthusiasten ein.
**Warum beitreten?**
- **Expertenunterstützung**: Löse Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams.
- **Lernen & Teilen**: Tausche Tipps und Tutorials aus, um deine Fähigkeiten zu verbessern.
- **Exklusive Vorschauen**: Erhalte frühzeitigen Zugang zu neuen Produktankündigungen und Vorschauen.
- **Sonderrabatte**: Genieße exklusive Rabatte auf unsere neuesten Produkte.
- **Festliche Aktionen und Verlosungen**: Nimm an Verlosungen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu erschaffen? Klicke auf [|link_sf_facebook|] und tritt noch heute bei!
.. _2.1.6_py_pi5_mcp3008:
2.1.6 Joystick (MCP3008)
=========================
.. note::
.. image:: ../img/mcp3008_and_adc0834.jpg
:width: 25%
:align: left
Je nach Kit-Version bitte prüfen, ob **ADC0834** oder **MCP3008** enthalten ist, und mit dem entsprechenden Abschnitt fortfahren.
Einführung
----------
In diesem Projekt lernen wir, wie ein Joystick funktioniert.
Wir bedienen den Joystick und zeigen die Ergebnisse auf dem Bildschirm an.
Benötigte Komponenten
----------------------
In diesem Projekt benötigen wir die folgenden Komponenten.
.. image:: ../python_pi5/img/image317-copy.png
Schaltplan
----------
Beim Auslesen der Joystick-Daten gibt es Unterschiede zwischen den Achsen:
Die Daten der X- und Y-Achse sind analog und müssen mit dem MCP3008 in digitale Werte umgewandelt werden.
Die Daten der Z-Achse sind digital, daher kannst du diese direkt über den GPIO auslesen – oder ebenfalls über den ADC.
.. list-table::
:widths: 30 30 30 30
:header-rows: 1
* - T-Board-Name
- Physical
- WiringPi
- BCM
* - SPICE0
- pin24
- 10
- 8
* - SPIMOSI
- pin19
- 12
- 10
* - SPIMISO
- pin21
- 13
- 9
* - SPISCLK
- pin23
- 14
- 11
* - GPIO22
- pin15
- 3
- 22
.. image:: ../python_pi5/img/schematic_2.1.9_joystick_mcp3008.png
Experimentelle Schritte
-----------------------
**Schritt 1:** Baue die Schaltung auf.
.. image:: ../python_pi5/img/july24_2.1.9_joystick_mcp3008.png
**Schritt 2:** Richte die SPI-Schnittstelle ein und installiere die ``spidev``-Bibliothek (siehe :ref:`spi_configuration` für detaillierte Anweisungen). Falls diese Schritte bereits erledigt sind, kannst du sie überspringen.
**Schritt 3:** Wechsle in den Ordner mit dem Code.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python-pi5
**Schritt 4:** Führe den Code aus.
.. raw:: html
.. code-block::
sudo python3 2.1.6-2_Joystick_zero.py
Nach dem Start des Codes bewege den Joystick – die entsprechenden Werte für X, Y und Btn werden auf dem Bildschirm angezeigt.
.. warning::
Falls die Fehlermeldung ``RuntimeError: Cannot determine SOC peripheral base address`` erscheint, siehe :ref:`faq_soc`.
**Code**
.. note::
Du kannst den folgenden Code **Ändern/Zurücksetzen/Kopieren/Ausführen/Stoppen**.
Vorher musst du jedoch in das Quellcode-Verzeichnis (z. B. ``davinci-kit-for-raspberry-pi/python-pi5``) wechseln.
Nach einer Änderung kannst du den Code direkt ausführen, um das Ergebnis zu sehen.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import Button
import spidev
import time
# Button initialisieren, verbunden mit GPIO-Pin 22 (Joystick SW-Pin)
BtnPin = Button(22)
# SPI-Kommunikation mit MCP3008 initialisieren
spi = spidev.SpiDev()
spi.open(0, 0) # SPI-Bus 0, Gerät CE0 öffnen
spi.max_speed_hz = 1000000 # SPI-Geschwindigkeit auf 1 MHz setzen
def read_adc(channel):
"""
Liest den analogen Wert vom angegebenen MCP3008-Kanal (0–7)
:param channel: ADC-Kanalnummer (0–7)
:return: 10-Bit-Integerwert (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:
# Hauptschleife zum Auslesen und Anzeigen der Joystick-Werte und des Button-Zustands
while True:
# X- und Y-Werte aus den MCP3008-Kanälen 0 und 1 lesen
x_val = read_adc(0) # Joystick VRX an CH0
y_val = read_adc(1) # Joystick VRY an CH1
# Zustand des Joystick-Buttons (SW) lesen
Btn_val = BtnPin.value # 0 = gedrückt, 1 = losgelassen
# Werte ausgeben
print('X: %d Y: %d Btn: %d' % (x_val, y_val, Btn_val))
# 0,2 Sekunden warten bis zur nächsten Messung
time.sleep(0.2)
# Strg+C wird sauber abgefangen
except KeyboardInterrupt:
spi.close()
**Code-Erklärung**
#. Dieser Abschnitt importiert die benötigten Bibliotheken:
* ``gpiozero.Button`` zum Auslesen des digitalen Zustands des Joystick-Buttons (SW-Pin).
* ``spidev`` für die SPI-Kommunikation mit dem MCP3008-ADC-Chip.
* ``time`` für Zeitverzögerungen zwischen den Messungen.
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import Button
import spidev
import time
#. Initialisiert den Button an GPIO22 (Joystick SW-Pin) und richtet die SPI-Schnittstelle auf Bus 0, Chip Select 0 (CE0) ein. Die SPI-Geschwindigkeit wird auf 1 MHz gesetzt.
.. code-block:: python
# Button initialisieren, verbunden mit GPIO-Pin 22 (Joystick SW-Pin)
BtnPin = Button(22)
# SPI-Kommunikation mit MCP3008 initialisieren
spi = spidev.SpiDev()
spi.open(0, 0) # SPI-Bus 0, Gerät CE0 öffnen
spi.max_speed_hz = 1000000 # SPI-Geschwindigkeit auf 1 MHz setzen
#. Definiert die Funktion ``read_adc(channel)``, um den analogen Wert eines bestimmten MCP3008-Kanals (0–7) auszulesen.
Es werden drei Bytes per SPI-Protokoll gesendet und ein 10-Bit-Wert (0–1023) zurückgegeben.
.. code-block:: python
def read_adc(channel):
"""
Liest den analogen Wert vom angegebenen MCP3008-Kanal (0–7)
:param channel: ADC-Kanalnummer (0–7)
:return: 10-Bit-Integerwert (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
#. In der Hauptschleife werden die analogen Werte von VRX (CH0) und VRY (CH1) sowie der Zustand des Joystick-Buttons ausgelesen.
Die Werte werden alle 0,2 Sekunden in der Konsole ausgegeben.
Bei Strg+C wird die SPI-Schnittstelle sauber geschlossen.
.. code-block:: python
try:
while True:
x_val = read_adc(0)
y_val = read_adc(1)
Btn_val = BtnPin.value
print('X: %d Y: %d Btn: %d' % (x_val, y_val, Btn_val))
time.sleep(0.2)
except KeyboardInterrupt:
spi.close()