Note
Bonjour et bienvenue dans la communauté des passionnés de SunFounder Raspberry Pi & Arduino & ESP32 sur Facebook ! Plongez plus profondément dans l’univers du Raspberry Pi, de l’Arduino et de l’ESP32 avec d’autres passionnés.
Pourquoi nous rejoindre ?
Support d’experts : Résolvez les problèmes après-vente et les défis techniques avec l’aide de notre communauté et de notre équipe.
Apprendre & Partager : Échangez des astuces et tutoriels pour améliorer vos compétences.
Aperçus exclusifs : Accédez en avant-première aux annonces de nouveaux produits et aperçus.
Réductions spéciales : Profitez de réductions exclusives sur nos derniers produits.
Promotions festives et concours : Participez à des concours et promotions spéciales pendant les fêtes.
👉 Prêt à explorer et créer avec nous ? Cliquez sur [Ici] et rejoignez-nous dès aujourd’hui !
3.1.4 Ventilateur intelligent (MCP3008)
Note
Selon la version de votre kit, identifiez si vous disposez de l’ADC0834 ou du MCP3008 et poursuivez avec la section correspondante.
Introduction
Dans ce projet, nous utiliserons des moteurs, des boutons et des thermistances pour créer un ventilateur intelligent, manuel + automatique, dont la vitesse est réglable.
Composants requis
Pour ce projet, nous avons besoin des composants suivants.
Schéma de câblage
Nom T-Board |
physique |
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 |
Procédure expérimentale
Étape 1 : Construire le circuit.
Note
Le module d’alimentation peut utiliser une pile 9V avec le clip pour pile 9V fourni dans le kit. Insérez le cavalier du module d’alimentation dans les rails d’alimentation 5V de la plaque d’essai.
Pour les utilisateurs du langage C
Étape 2 : Accédez au dossier du code.
cd ~/davinci-kit-for-raspberry-pi/c/3.1.4-2/
Étape 3 : Compiler.
gcc 3.1.4_SmartFan.c -o SmartFan -lwiringPi -lm
Étape 4 : Exécuter l’exécutable ci-dessus.
./SmartFan
Lorsque le code s’exécute, démarrez le ventilateur en appuyant sur le bouton. Chaque pression augmente ou diminue le niveau de vitesse d’une unité. Il y a 5 niveaux de vitesse : 0~4. Lorsque vous atteignez le 4ème niveau et appuyez à nouveau, le ventilateur s’arrête (0).
Une variation de température supérieure à ±2℃ entraîne automatiquement une augmentation ou diminution d’un niveau de vitesse.
Note
Si le programme ne fonctionne pas après exécution ou si un message d’erreur apparaît : « wiringPi.h: No such file or directory », veuillez vous référer à Installer et vérifier 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; // Bit de démarrage
buffer[1] = (8 + channel) << 4; // Mode à extrémité unique et canal
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; // Utiliser 3,3V comme Vref pour 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;
}
Explication du code
int read_ADC(int channel)
{
if (channel < 0 || channel > 7) return -1;
unsigned char buffer[3];
buffer[0] = 1; // Bit de démarrage
buffer[1] = (8 + channel) << 4; // Mode unipolaire et canal
buffer[2] = 0;
wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
int result = ((buffer[1] & 3) << 8) | buffer[2];
return result;
}
Cette fonction permet de lire une entrée analogique depuis le MCP3008 sur le canal spécifié. Elle envoie une commande SPI de 3 octets et retourne une valeur numérique 10 bits comprise entre 0 et 1023.
int temperture()
{
int analogVal = read_ADC(0);
double Vr = 3.3 * analogVal / 1023.0; // Utiliser 3,3 V comme Vref pour le 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;
}
La fonction temperture() lit le signal analogique du thermistor via le MCP3008,
calcule la tension et la résistance, puis convertit la valeur en Celsius et en Fahrenheit en utilisant
la formule du thermistor (approximation Steinhart–Hart).
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;
}
La fonction motor() contrôle la vitesse du ventilateur via PWM.
Le niveau varie de 0 à 4, où 0 arrête le ventilateur et chaque niveau augmente le cycle de service de 25 %.
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);
}
La fonction setup() initialise WiringPi, configure l’interface SPI, configure le PWM
et définit les broches GPIO nécessaires au contrôle du moteur et à l’entrée du bouton.
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;
}
La fonction main() contient la boucle principale du programme :
Vérifie en continu l’état du bouton et lit la température actuelle.
Lorsqu’on appuie sur le bouton, le niveau du ventilateur augmente (cycle de 0 à 4) et enregistre la température.
Si la température change de ± 2 °C, la vitesse du ventilateur s’ajuste automatiquement.
Appelle
motor(level)pour mettre à jour la sortie PWM selon le niveau.
Pour les utilisateurs du langage Python
Étape 2 : Configurez l’interface SPI et installez la bibliothèque spidev (voir Configuration SPI pour les instructions détaillées).
Si vous avez déjà effectué ces étapes, vous pouvez les ignorer.
Étape 3 : Accédez au dossier contenant le code.
cd ~/davinci-kit-for-raspberry-pi/python
Étape 4 : Exécutez.
sudo python3 3.1.4-2_SmartFan.py
Lorsque le code s’exécute, démarrez le ventilateur en appuyant sur le bouton. Chaque pression change la vitesse d’un niveau. Il y a 5 niveaux possibles : 0 à 4. À la 4ème vitesse, une pression supplémentaire arrête le ventilateur (niveau 0).
Dès que la température augmente ou diminue de plus de 2 °C, la vitesse s’ajuste automatiquement d’un niveau.
Code
Note
Vous pouvez Modifier/Réinitialiser/Copier/Exécuter/Arrêter le code ci-dessous. Avant cela,
assurez-vous d’être dans le chemin du code source comme davinci-kit-for-raspberry-pi/python.
Après modification, vous pouvez l’exécuter directement pour voir l’effet.
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
# Configuration des broches
BTN_PIN = 22 # Bouton GPIO (broche physique 15)
MOTOR_IN1 = 5 # Moteur avant
MOTOR_IN2 = 6 # Moteur arrière
MOTOR_EN = 13 # Broche d’activation PWM
# Configuration GPIO
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)
# Configuration PWM pour le contrôle de la vitesse du moteur
pwm = GPIO.PWM(MOTOR_EN, 1000) # Fréquence de 1 kHz
pwm.start(0)
# Initialisation SPI pour MCP3008
spi = spidev.SpiDev()
spi.open(0, 0) # Bus 0, CE0
spi.max_speed_hz = 1000000 # 1 MHz
# Variables globales
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) # Mapper le niveau (1–4) à 25 %–100 %
return level
def changeLevel(channel):
global level, currentTemp, markTemp
print("Bouton pressé")
level = (level + 1) % 5
markTemp = currentTemp
# Détection d’événement pour le bouton
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()
Explication du code
Importer les modules nécessaires :
RPi.GPIOpour le contrôle GPIO (bouton et moteur)spidevpour la communication avec l’ADC MCP3008timepour les temporisationsmathpour les calculs logarithmiques de température
#!/usr/bin/env python3 import RPi.GPIO as GPIO import spidev import time import math
Configurer les broches GPIO :
Bouton sur GPIO22 (avec résistance de tirage interne)
Contrôle moteur : GPIO5 (avant), GPIO6 (arrière), GPIO13 (activation PWM)
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)
Initialiser la communication SPI avec MCP3008 (Bus 0, CE0) à 1 MHz
spi = spidev.SpiDev() spi.open(0, 0) spi.max_speed_hz = 1000000
Définir ``read_adc()`` : lit une valeur analogique 10 bits (0–1023) sur le canal MCP3008
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
Définir ``temperature()`` : convertit la tension analogique en résistance, applique la formule du thermistor et retourne la température en Celsius
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
Définir ``motor_run()`` :
Niveau 0 : arrêt du moteur
Niveaux 1–4 : PWM de 25 % à 100 % (moteur avant)
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
Définir ``changeLevel()`` : fonction de rappel pour le bouton qui incrémente le niveau du moteur et enregistre la température de référence
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)
Boucle ``main()`` :
Surveille les variations de température par rapport à la référence
Ajuste automatiquement la vitesse si ± 2 °C
Met à jour le moteur toutes les 0,2 s
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)
Nettoyage à l’arrêt (Ctrl + C) : arrêt PWM, nettoyage GPIO, fermeture SPI
try: main() except KeyboardInterrupt: pass finally: pwm.stop() GPIO.cleanup() spi.close()