Bemerkung
Hallo, willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauche tiefer ein in Raspberry Pi, Arduino und ESP32 zusammen mit anderen Enthusiasten.
Warum beitreten?
Experten-Support: 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 Gewinnspielen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu erschaffen? Klicke auf [hier] und trete noch heute bei!
3.1.4 Intelligenter Ventilator (MCP3008)
Bemerkung
Abhängig von deiner Bausatzversion ü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:
Schaltplan
T-Board Name |
Physisch |
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 |
Experimentelle Schritte
Schritt 1: Baue die Schaltung auf.
Bemerkung
Das Strommodul kann mit einer 9V-Batterie und dem im Kit enthaltenen 9V-Batterieclip betrieben werden. Stecke den Jumper des Strommoduls in die 5V-Leiste des Breadboards.
Für C-Sprach-Nutzer
Schritt 2: Wechsle in den Code-Ordner.
cd ~/davinci-kit-for-raspberry-pi/c/3.1.4-2/
Schritt 3: Kompilieren.
gcc 3.1.4_SmartFan.c -o SmartFan -lwiringPi -lm
Schritt 4: Die erstellte ausführbare Datei ausführen.
./SmartFan
Während der Code läuft, starte den Ventilator durch Drücken des Tasters. Jeder Tastendruck erhöht oder verringert die Stufe um 1. Es gibt 5 Stufen: 0~4. Bei Stufe 4 und erneutem Drücken stoppt der Ventilator (Stufe 0).
Wenn sich die Temperatur um mehr als ±2 ℃ ändert, passt sich die Geschwindigkeit automatisch um eine Stufe an.
Bemerkung
Falls es nach dem Start nicht funktioniert oder eine Fehlermeldung wie „wiringPi.h: No such file or directory“ erscheint, siehe Installieren und Überprüfen von WiringPi.
Code
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <softPwm.h>
#include <math.h>
#define SPI_CHANNEL 0
#define SPI_SPEED 1000000
#define MotorPin1 21
#define MotorPin2 22
#define MotorEnable 23
#define BtnPin 3
int read_ADC(int channel)
{
if (channel < 0 || channel > 7) return -1;
unsigned char buffer[3];
buffer[0] = 1; // Start bit
buffer[1] = (8 + channel) << 4; // Single-ended mode and channel
buffer[2] = 0;
wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
int result = ((buffer[1] & 3) << 8) | buffer[2];
return result;
}
int temperture()
{
int analogVal = read_ADC(0);
double Vr = 3.3 * analogVal / 1023.0; // Use 3.3V as Vref for MCP3008
double Rt = 10000.0 * Vr / (3.3 - Vr);
double temp = 1 / (((log(Rt / 10000.0)) / 3950.0) + (1 / (273.15 + 25.0)));
double cel = temp - 273.15;
double Fah = cel * 1.8 + 32;
printf("Celsius: %.2f C Fahrenheit: %.2f F\n", cel, Fah);
return (int)cel;
}
int motor(int level)
{
if (level == 0) {
digitalWrite(MotorEnable, LOW);
return 0;
}
if (level >= 4) {
level = 4;
}
digitalWrite(MotorEnable, HIGH);
softPwmWrite(MotorPin1, level * 25);
return level;
}
void setup()
{
if (wiringPiSetup() == -1) {
printf("wiringPi setup failed!\n");
return;
}
if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
printf("SPI setup failed!\n");
return;
}
softPwmCreate(MotorPin1, 0, 100);
softPwmCreate(MotorPin2, 0, 100);
pinMode(MotorEnable, OUTPUT);
pinMode(BtnPin, INPUT);
}
int main(void)
{
setup();
int currentState, lastState = 0;
int level = 0;
int currentTemp, markTemp = 0;
while (1) {
currentState = digitalRead(BtnPin);
currentTemp = temperture();
if (currentTemp <= 0) continue;
if (currentState == 1 && lastState == 0) {
level = (level + 1) % 5;
markTemp = currentTemp;
delay(500);
}
lastState = currentState;
if (level != 0) {
if (currentTemp - markTemp <= -2) {
level = level - 1;
markTemp = currentTemp;
}
if (currentTemp - markTemp >= 2) {
level = level + 1;
markTemp = currentTemp;
}
}
level = motor(level);
}
return 0;
}
Code-Erklärung
int read_ADC(int channel)
{
if (channel < 0 || channel > 7) return -1;
unsigned char buffer[3];
buffer[0] = 1; // Start bit
buffer[1] = (8 + channel) << 4; // Single-ended mode and channel
buffer[2] = 0;
wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
int result = ((buffer[1] & 3) << 8) | buffer[2];
return result;
}
Diese Funktion liest einen analogen Eingang des MCP3008 am angegebenen Kanal. Sie sendet einen 3-Byte-SPI-Befehl und gibt einen 10-Bit-Digitalwert zwischen 0–1023 zurück.
int temperture()
{
int analogVal = read_ADC(0);
double Vr = 3.3 * analogVal / 1023.0; // Use 3.3V as Vref for MCP3008
double Rt = 10000.0 * Vr / (3.3 - Vr);
double temp = 1 / (((log(Rt / 10000.0)) / 3950.0) + (1 / (273.15 + 25.0)));
double cel = temp - 273.15;
double Fah = cel * 1.8 + 32;
printf("Celsius: %.2f C Fahrenheit: %.2f F\n", cel, Fah);
return (int)cel;
}
Die Funktion temperture() liest das analoge Signal des Thermistors über den MCP3008,
berechnet Spannung und Widerstand und wandelt diese dann mit der Thermistor-Formel
(Steinhart–Hart-Approximation) in Celsius und Fahrenheit um.
int motor(int level)
{
if (level == 0) {
digitalWrite(MotorEnable, LOW);
return 0;
}
if (level >= 4) {
level = 4;
}
digitalWrite(MotorEnable, HIGH);
softPwmWrite(MotorPin1, level * 25);
return level;
}
Die Funktion motor() steuert die Lüftergeschwindigkeit über PWM.
Die Stufe reicht von 0–4, wobei 0 den Lüfter ausschaltet und jede Stufe den Tastgrad um 25 % erhöht.
void setup()
{
if (wiringPiSetup() == -1) {
printf("wiringPi setup failed!\n");
return;
}
if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
printf("SPI setup failed!\n");
return;
}
softPwmCreate(MotorPin1, 0, 100);
softPwmCreate(MotorPin2, 0, 100);
pinMode(MotorEnable, OUTPUT);
pinMode(BtnPin, INPUT);
}
Die Funktion setup() initialisiert WiringPi, richtet SPI ein und konfiguriert PWM sowie GPIO-Pins
für Motorsteuerung und Tastereingabe.
int main(void)
{
setup();
int currentState, lastState = 0;
int level = 0;
int currentTemp, markTemp = 0;
while (1) {
currentState = digitalRead(BtnPin);
currentTemp = temperture();
if (currentTemp <= 0) continue;
if (currentState == 1 && lastState == 0) {
level = (level + 1) % 5;
markTemp = currentTemp;
delay(500);
}
lastState = currentState;
if (level != 0) {
if (currentTemp - markTemp <= -2) {
level = level - 1;
markTemp = currentTemp;
}
if (currentTemp - markTemp >= 2) {
level = level + 1;
markTemp = currentTemp;
}
}
level = motor(level);
}
return 0;
}
Die Funktion main() enthält die Programmschleife:
Überprüft ständig den Tasterstatus und liest die aktuelle Temperatur.
Bei Tastendruck erhöht sich die Stufe (zyklisch 0–4) und die Temperatur wird gespeichert.
Wenn sich die Temperatur um ±2 ℃ ändert, wird die Lüftergeschwindigkeit automatisch angepasst.
Ruft
motor(level)auf, um die PWM-Ausgabe entsprechend zu setzen.
Für Python-Sprach-Nutzer
Schritt 2: SPI-Schnittstelle einrichten und spidev-Bibliothek installieren (siehe SPI-Konfiguration). Falls bereits geschehen, überspringen.
Schritt 3: Wechsle in den Code-Ordner.
cd ~/davinci-kit-for-raspberry-pi/python
Schritt 4: Ausführen.
sudo python3 3.1.4-2_SmartFan.py
Funktionsweise: Wie bei der C-Version wird der Lüfter über den Taster gesteuert, Temperaturänderungen um ±2 ℃ passen die Stufe automatisch an.
Code
Bemerkung
Du kannst den Code unten Ändern/Zurücksetzen/Kopieren/Ausführen/Stoppen.
Wechsle vorher in den Quellcodepfad davinci-kit-for-raspberry-pi/python.
Nach Änderungen kannst du ihn direkt ausführen, um den Effekt zu sehen.
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
# Pin configuration
BTN_PIN = 22 # Button GPIO (physical pin 15)
MOTOR_IN1 = 5 # Motor forward
MOTOR_IN2 = 6 # Motor backward
MOTOR_EN = 13 # PWM enable pin
# GPIO setup
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 setup for motor speed control
pwm = GPIO.PWM(MOTOR_EN, 1000) # 1kHz frequency
pwm.start(0)
# Initialize SPI for MCP3008
spi = spidev.SpiDev()
spi.open(0, 0) # Bus 0, CE0
spi.max_speed_hz = 1000000 # 1 MHz
# Global variables
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) # Map level (1–4) to 25%–100%
return level
def changeLevel(channel):
global level, currentTemp, markTemp
print("Button pressed")
level = (level + 1) % 5
markTemp = currentTemp
# Add event detection for button press
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
Notwendige Module importieren:
RPi.GPIOfür GPIO-Steuerung (Taster und Motor),spidevfür die Kommunikation mit dem MCP3008 ADC,timefür Verzögerungen,mathfür Temperaturberechnungen mit Logarithmusfunktionen.
#!/usr/bin/env python3 import RPi.GPIO as GPIO import spidev import time import math
GPIO-Pins einrichten:
Taster an GPIO22 (mit internem Pull-up),
Motorsteuerung über GPIO5 (vorwärts), GPIO6 (rückwärts) und GPIO13 (PWM enable).
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 MCP3008 initialisieren (Bus 0, CE0, 1 MHz).
spi = spidev.SpiDev() spi.open(0, 0) spi.max_speed_hz = 1000000
read_adc()-Funktion definiert, um einen 10-Bit-Analogwert (0–1023) vom angegebenen Kanal (0–7) zu lesen.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
temperature()-Funktion:Wandelt die analoge Spannung in Widerstand um,
Nutzt die Steinhart–Hart-Gleichung, um die Temperatur in Celsius zu berechnen.
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
motor_run():Stoppt den Motor bei Stufe 0,
Läuft vorwärts mit steigender Geschwindigkeit bei Stufen 1–4 (PWM 25 %–100 %).
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 für Tastendruck:Erhöht die Stufe zyklisch (0–4),
Speichert die aktuelle Temperatur als neuen Referenzwert.
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:Überwacht Temperaturänderungen,
Passt Stufe bei ±2 ℃ Änderung automatisch an,
Aktualisiert die Motorgeschwindigkeit alle 0,2 Sekunden.
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
Ctrl+Cordnungsgemäß aufräumen (Motor stoppen, GPIO zurücksetzen, SPI schließen).try: main() except KeyboardInterrupt: pass finally: pwm.stop() GPIO.cleanup() spi.close()