Note

Bonjour et bienvenue dans la communauté Facebook des passionnés de SunFounder Raspberry Pi & Arduino & ESP32 ! Plongez plus profondément dans l’univers du Raspberry Pi, Arduino et ESP32 avec d’autres passionnés.

Pourquoi nous rejoindre ?

  • Support expert : Résolvez vos problèmes après-vente et vos défis techniques avec l’aide de notre communauté et de notre équipe.

  • Apprendre & partager : Échangez des conseils et des tutoriels pour améliorer vos compétences.

  • Aperçus exclusifs : Accédez en avant-première aux annonces de nouveaux produits et aux aperçus.

  • Réductions spéciales : Profitez de remises exclusives sur nos derniers produits.

  • Promotions festives et cadeaux : Participez à des concours et à des promotions spéciales.

👉 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

../_images/mcp3008_and_adc0834.jpg

Selon la version de votre kit, veuillez identifier si vous disposez du ADC0834 ou du MCP3008 et suivre la section correspondante.

Introduction

Dans ce projet, nous allons utiliser des moteurs, des boutons et des thermistances pour créer un ventilateur intelligent manuel + automatique dont la vitesse du vent est réglable.

Composants nécessaires

Pour ce projet, nous avons besoin des composants suivants.

../_images/list2_Smart_Fan.png

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

../_images/schematic_3.1.4_smart_fan_mcp3008.png

Procédure expérimentale

Étape 1 : Construire le circuit.

../_images/july24_3.1.4_smart_fan_mcp3008.png

Note

Le module d’alimentation peut utiliser une pile de 9 V avec le clip pour pile 9 V inclus dans le kit. Insérez le cavalier du module d’alimentation dans les rails 5 V de la plaque d’essai.

../_images/image118.jpeg

Étape 2 : Accéder 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 le fichier 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 la vitesse d’un niveau. Il existe 5 niveaux : 0~4. Lorsque vous êtes au 4ème niveau et que vous appuyez sur le bouton, le ventilateur s’arrête (vitesse 0).

Dès que la température augmente ou diminue de plus de 2 ℃, la vitesse augmente ou diminue automatiquement d’un niveau.

Note

Si le programme ne fonctionne pas après l’exécution ou si un message d’erreur apparaît : « wiringPi.h: No such file or directory », veuillez consulter 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 à entrée 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.3 V 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("Échec de l’initialisation de wiringPi !\n");
        return;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("Échec de l’initialisation SPI !\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 à entrée unique 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 l’entrée analogique sur le canal spécifié du MCP3008. Elle envoie une commande SPI de 3 octets et renvoie 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 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 de la thermistance via le MCP3008, calcule la tension, la résistance, puis convertit en Celsius et Fahrenheit en utilisant la formule de la thermistance (approximation de 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 va de 0 à 4 : 0 éteint le ventilateur et chaque niveau augmente le cycle de service de 25 %.

void setup()
{
    if (wiringPiSetup() == -1) {
        printf("Échec de l’initialisation de wiringPi !\n");
        return;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("Échec de l’initialisation SPI !\n");
        return;
    }

    softPwmCreate(MotorPin1, 0, 100);
    softPwmCreate(MotorPin2, 0, 100);
    pinMode(MotorEnable, OUTPUT);
    pinMode(BtnPin, INPUT);
}

La fonction setup() initialise WiringPi, configure le SPI, paramètre le PWM et les broches GPIO nécessaires pour le 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 :

  1. Vérifie constamment l’état du bouton et lit la température actuelle.

  2. Lors d’un appui sur le bouton, le niveau du ventilateur augmente (cycle 0–4) et la température est enregistrée.

  3. Si la température varie de ±2 °C, la vitesse du ventilateur s’ajuste automatiquement.

  4. Appelle motor(level) pour mettre à jour la sortie PWM selon le niveau actuel.