.. note::
Hallo, 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 Gewinnspiele**: Nimm an Gewinnspielen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu erkunden und zu kreieren? Klicke [|link_sf_facebook|] und tritt noch heute bei!
.. _4.1.10_py_mcp3008:
4.1.10 Intelligenter Ventilator (MCP3008)
============================================================
.. note::
.. image:: ../img/mcp3008_and_adc0834.jpg
:width: 25%
:align: left
Je nach deiner Kit-Version überprüfe bitte, ob du **ADC0834** oder **MCP3008** hast, und fahre mit dem entsprechenden Abschnitt fort.
Einführung
----------
In diesem Projekt verwenden wir Motoren, Taster und Thermistoren, um einen manuellen + automatischen intelligenten Ventilator zu bauen, dessen Windgeschwindigkeit einstellbar ist.
Benötigte Komponenten
---------------------
Für dieses Projekt benötigen wir die folgenden Komponenten.
.. image:: ../img/list2_Smart_Fan.png
:width: 800
:align: center
Es ist auf jeden Fall praktisch, ein komplettes Kit zu kaufen. Hier ist der Link:
.. list-table::
:widths: 20 20 20
:header-rows: 1
* - Name
- ENTHALTENE ARTIKEL
- LINK
* - Raphael Kit
- 337
- |link_Raphael_kit|
Du kannst die Komponenten auch einzeln über die folgenden Links kaufen.
.. list-table::
:widths: 30 20
:header-rows: 1
* - KOMPONENTENBESCHREIBUNG
- KAUFLINK
* - :ref:`cpn_gpio_board`
- |link_gpio_board_buy|
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_power_module`
- \-
* - :ref:`cpn_thermistor`
- |link_thermistor_buy|
* - :ref:`cpn_l293d`
- \-
* - :ref:`cpn_mcp3008`
- \-
* - :ref:`cpn_button`
- |link_button_buy|
* - :ref:`cpn_motor`
- |link_motor_buy|
Schaltplan
----------
============ ======== ======== ===
T-Board-Name physical wiringPi BCM
SPICE0 Pin 24 10 8
SPIMOSI Pin 19 12 10
SPIMISO Pin 21 13 9
SPISCLK Pin 23 14 11
GPIO22 Pin 15 3 22
GPIO5 Pin 29 21 5
GPIO6 Pin 31 22 6
GPIO13 Pin 33 23 13
============ ======== ======== ===
.. image:: ../img/schematic_3.1.4_smart_fan_mcp3008.png
:align: center
Experimentelle Schritte
-----------------------
**Schritt 1:** Baue die Schaltung auf.
.. image:: ../img/july24_3.1.4_smart_fan_mcp3008.png
.. note::
Das Netzmodul kann mit einer 9V-Batterie und dem 9V-Batterieanschluss aus dem Kit betrieben werden.
Stecke den Jumper des Netzmoduls in die 5V-Stromschienen des Breadboards.
.. image:: ../img/image118.jpeg
:align: center
**Schritt 2:** Richte die SPI-Schnittstelle ein und installiere die ``spidev``-Bibliothek (siehe :ref:`spi_configuration` für detaillierte Anweisungen). Wenn du diese Schritte bereits abgeschlossen hast, kannst du diesen Schritt überspringen.
**Schritt 3:** Wechsle in den Ordner mit dem Code.
.. raw:: html
.. code-block::
cd ~/raphael-kit/python
**Schritt 4:** Führe den Code aus.
.. raw:: html
.. code-block::
sudo python3 4.1.10-2_SmartFan.py
Während der Code läuft, starte den Ventilator, indem du den Knopf drückst.
Bei jedem Drücken wird eine Geschwindigkeitsstufe hoch- oder runtergeschaltet.
Es gibt **5** Geschwindigkeitsstufen: **0~4**. Wenn die 4. Stufe erreicht ist und der Knopf erneut gedrückt wird, stoppt der Ventilator bei Windstufe **0**.
Sobald sich die Temperatur um mehr als 2 °C ändert, wird die Geschwindigkeit automatisch um eine Stufe erhöht oder verringert.
Code
----
.. note::
Du kannst den untenstehenden Code **Bearbeiten/Zurücksetzen/Kopieren/Ausführen/Stoppen**.
Wechsle vorher in den Quellcodepfad wie ``raphael-kit/python``.
Nach dem Ändern kannst du den Code direkt ausführen, um das Ergebnis zu sehen.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
# Pin-Konfiguration
BTN_PIN = 22 # Taster
MOTOR_IN1 = 5 # Motor vorwärts
MOTOR_IN2 = 6 # Motor rückwärts
MOTOR_EN = 13 # PWM-Pin
# GPIO einrichten
GPIO.setmode(GPIO.BCM)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(MOTOR_IN1, GPIO.OUT)
GPIO.setup(MOTOR_IN2, GPIO.OUT)
GPIO.setup(MOTOR_EN, GPIO.OUT)
# PWM für Motorsteuerung
pwm = GPIO.PWM(MOTOR_EN, 1000) # 1kHz
pwm.start(0)
# SPI initialisieren (MCP3008)
spi = spidev.SpiDev()
spi.open(0, 0) # Bus 0, CE0
spi.max_speed_hz = 1000000 # 1 MHz
# Globale Variablen
level = 0
currentTemp = 0
markTemp = 0
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
def temperature():
analogVal = read_adc(0)
Vr = 3.3 * analogVal / 1023.0
Rt = 10000.0 * Vr / (3.3 - Vr)
tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
Cel = tempK - 273.15
return Cel
def motor_run(level):
if level == 0:
GPIO.output(MOTOR_IN1, GPIO.LOW)
GPIO.output(MOTOR_IN2, GPIO.LOW)
pwm.ChangeDutyCycle(0)
return 0
if level >= 4:
level = 4
GPIO.output(MOTOR_IN1, GPIO.HIGH)
GPIO.output(MOTOR_IN2, GPIO.LOW)
pwm.ChangeDutyCycle(level * 25) # 25%–100%
return level
def changeLevel(channel):
global level, currentTemp, markTemp
print("Button pressed")
level = (level + 1) % 5
markTemp = currentTemp
# Ereigniserkennung für Taster
GPIO.add_event_detect(BTN_PIN, GPIO.FALLING, callback=changeLevel, bouncetime=300)
def main():
global level, currentTemp, markTemp
markTemp = temperature()
while True:
currentTemp = temperature()
if level != 0:
if currentTemp - markTemp <= -2:
level -= 1
markTemp = currentTemp
elif currentTemp - markTemp >= 2:
if level < 4:
level += 1
markTemp = currentTemp
level = motor_run(level)
time.sleep(0.2)
try:
main()
except KeyboardInterrupt:
pass
finally:
pwm.stop()
GPIO.cleanup()
spi.close()
Code-Erklärung
--------------
#. Benötigte Module importieren:
- ``RPi.GPIO`` für die Steuerung von GPIO (Taster und Motor),
- ``spidev`` für die Kommunikation mit MCP3008,
- ``time`` für Verzögerungen,
- ``math`` für Temperaturberechnungen.
.. code-block:: python
import RPi.GPIO as GPIO
import spidev
import time
import math
#. GPIO-Pins einrichten:
- Taster auf GPIO22 (interner Pull-Up),
- Motorsteuerung über GPIO5 (vorwärts), GPIO6 (rückwärts) und GPIO13 (PWM).
.. code-block:: python
BTN_PIN = 22
MOTOR_IN1 = 5
MOTOR_IN2 = 6
MOTOR_EN = 13
GPIO.setmode(GPIO.BCM)
GPIO.setup(BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(MOTOR_IN1, GPIO.OUT)
GPIO.setup(MOTOR_IN2, GPIO.OUT)
GPIO.setup(MOTOR_EN, GPIO.OUT)
pwm = GPIO.PWM(MOTOR_EN, 1000)
pwm.start(0)
#. SPI-Kommunikation mit dem MCP3008 initialisieren (Bus 0, CE0) bei 1 MHz.
.. code-block:: python
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000
#. Funktion ``read_adc()`` definiert, um einen 10-Bit-Analogwert (0–1023) vom angegebenen MCP3008-Kanal zu lesen.
.. 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
#. Funktion ``temperature()``:
- Analogspannung in Widerstand umrechnen,
- Steinhart–Hart-Gleichung anwenden, um die Temperatur in °C zu berechnen.
.. code-block:: python
def temperature():
analogVal = read_adc(0)
Vr = 3.3 * analogVal / 1023.0
Rt = 10000.0 * Vr / (3.3 - Vr)
tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
Cel = tempK - 273.15
return Cel
#. Funktion ``motor_run()``:
- Motor bei Stufe 0 stoppen,
- Motor vorwärts laufen lassen bei Stufe 1–4 mit PWM 25 % bis 100 %.
.. code-block:: python
def motor_run(level):
if level == 0:
GPIO.output(MOTOR_IN1, GPIO.LOW)
GPIO.output(MOTOR_IN2, GPIO.LOW)
pwm.ChangeDutyCycle(0)
return 0
if level >= 4:
level = 4
GPIO.output(MOTOR_IN1, GPIO.HIGH)
GPIO.output(MOTOR_IN2, GPIO.LOW)
pwm.ChangeDutyCycle(level * 25)
return level
#. ``changeLevel()``-Callback bei Tastendruck:
- Motorstufe zyklisch erhöhen (0 bis 4),
- aktuelle Temperatur als Referenz speichern.
.. code-block:: python
def changeLevel(channel):
global level, currentTemp, markTemp
print("Button pressed")
level = (level + 1) % 5
markTemp = currentTemp
GPIO.add_event_detect(BTN_PIN, GPIO.FALLING, callback=changeLevel, bouncetime=300)
#. ``main()``-Schleife:
- Temperaturänderung überwachen,
- Bei -2 °C Stufe senken, bei +2 °C Stufe erhöhen,
- Motorgeschwindigkeit entsprechend anpassen.
.. code-block:: python
def main():
global level, currentTemp, markTemp
markTemp = temperature()
while True:
currentTemp = temperature()
if level != 0:
if currentTemp - markTemp <= -2:
level -= 1
markTemp = currentTemp
elif currentTemp - markTemp >= 2:
if level < 4:
level += 1
markTemp = currentTemp
level = motor_run(level)
time.sleep(0.2)
#. Hauptfunktion starten und bei Strg+C aufräumen (Motor stoppen, GPIO und SPI freigeben).
.. code-block:: python
try:
main()
except KeyboardInterrupt:
pass
finally:
pwm.stop()
GPIO.cleanup()
spi.close()