Nota

Ciao, benvenuto nella Community Facebook di appassionati di SunFounder Raspberry Pi & Arduino & ESP32! Approfondisci Raspberry Pi, Arduino ed ESP32 con altri appassionati.

Perché unirsi?

  • Supporto esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara e condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.

  • Anteprime esclusive: Ottieni l’accesso anticipato agli annunci di nuovi prodotti e alle anteprime.

  • Sconti speciali: Goditi sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni festive e giveaway: Partecipa a giveaway e promozioni festive.

👉 Pronto a esplorare e creare con noi? Clicca [Qui] e unisciti oggi stesso!

4.1.10 Ventilatore Intelligente (MCP3008)

Nota

../_images/mcp3008_and_adc0834.jpg

A seconda della versione del tuo kit, identifica se hai ADC0834 o MCP3008 e procedi con la sezione corrispondente.

Introduzione

In questo progetto, utilizzeremo motori, pulsanti e termistori per realizzare un ventilatore intelligente manuale + automatico con velocità del vento regolabile.

Componenti richiesti

In questo progetto, ci servono i seguenti componenti.

../_images/list2_Smart_Fan.png

È sicuramente conveniente acquistare un kit completo, ecco il link:

Nome

ARTICOLI IN QUESTO KIT

LINK

Raphael Kit

337

Raphael Kit

Puoi anche acquistarli separatamente dai link sottostanti.

INTRODUZIONE COMPONENTE

LINK DI ACQUISTO

Scheda di estensione GPIO

ACQUISTA

Breadboard

ACQUISTA

Cavi Jumper

ACQUISTA

Resistore

ACQUISTA

Modulo di Alimentazione

-

Termistore

ACQUISTA

L293D

-

MCP3008

-

Pulsante

ACQUISTA

Motore DC

ACQUISTA

Schema elettrico

Nome T-Board

fisico

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

Procedure sperimentali

Passo 1: Costruisci il circuito.

../_images/july24_3.1.4_smart_fan_mcp3008.png

Nota

Il modulo di alimentazione può utilizzare una batteria da 9V con l’apposito connettore presente nel kit. Inserisci il ponticello del modulo di alimentazione nel bus da 5V della breadboard.

../_images/image118.jpeg

Passo 2: Configura l’interfaccia SPI e installa la libreria spidev (vedi Configurazione SPI per istruzioni dettagliate). Se hai già completato questi passaggi, puoi saltarli.

Passo 3: Vai nella cartella del codice.

cd ~/raphael-kit/python

Passo 4: Esegui.

sudo python3 4.1.10-2_SmartFan.py

Durante l’esecuzione del codice, avvia il ventilatore premendo il pulsante. Ogni volta che premi, la velocità aumenta o diminuisce di 1 livello. Sono presenti 5 livelli di velocità: 0~4. Quando è impostato il livello di velocità e premi nuovamente il pulsante, il ventilatore si ferma con velocità 0.

Quando la temperatura aumenta o diminuisce di più di 2℃, la velocità cambia automaticamente di 1 livello in più o in meno.

Codice

Nota

Puoi Modificare/Resettare/Copiare/Eseguire/Fermare il codice qui sotto. Prima però devi andare nel percorso del codice sorgente come raphael-kit/python. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

#!/usr/bin/env python3

import RPi.GPIO as GPIO
import spidev
import time
import math

# Configurazione pin
BTN_PIN = 22            # Pulsante GPIO (pin fisico 15)
MOTOR_IN1 = 5           # Motore avanti
MOTOR_IN2 = 6           # Motore indietro
MOTOR_EN = 13           # Pin abilitazione PWM

# Impostazione 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)

# Impostazione PWM per il controllo della velocità del motore
pwm = GPIO.PWM(MOTOR_EN, 1000)  # Frequenza 1kHz
pwm.start(0)

# Inizializzazione SPI per MCP3008
spi = spidev.SpiDev()
spi.open(0, 0)  # Bus 0, CE0
spi.max_speed_hz = 1000000  # 1 MHz

# Variabili globali
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)  # Mappa livello (1–4) a 25%–100%
    return level

def changeLevel(channel):
    global level, currentTemp, markTemp
    print("Pulsante premuto")
    level = (level + 1) % 5
    markTemp = currentTemp

# Aggiungi rilevamento evento per la pressione del pulsante
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()

Spiegazione del codice

  1. Importa i moduli richiesti:

    • RPi.GPIO per il controllo GPIO (pulsante e motore),

    • spidev per la comunicazione con l’ADC MCP3008,

    • time per i ritardi,

    • math per il calcolo della temperatura con funzioni logaritmiche.

    import RPi.GPIO as GPIO
    import spidev
    import time
    import math
    
  2. Imposta i pin GPIO:

    • Pulsante su GPIO22 (con pull-up interno),

    • Controllo motore tramite GPIO5 (avanti), GPIO6 (indietro) e GPIO13 (abilitazione 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)
    
  3. Inizializza la comunicazione SPI con MCP3008 (Bus 0, CE0) a 1 MHz.

    spi = spidev.SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    
  4. Definisce read_adc() per leggere un valore analogico a 10 bit (0–1023) dal canale MCP3008 specificato (0–7).

    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
    
  5. Definisce temperature() per:

    • Convertire la tensione analogica in resistenza,

    • Applicare l’equazione di Steinhart–Hart per calcolare la temperatura in 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
    
  6. Definisce motor_run() per:

    • Fermare il motore al livello 0,

    • Far girare il motore in avanti con velocità crescente basata sui livelli 1–4, con duty cycle PWM dal 25% al 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
    
  7. Definisce la callback changeLevel() per la pressione del pulsante:

    • Aumenta ciclicamente il livello del motore (0 a 4),

    • Registra la temperatura corrente come nuovo riferimento.

    def changeLevel(channel):
        global level, currentTemp, markTemp
        print("Pulsante premuto")
        level = (level + 1) % 5
        markTemp = currentTemp
    
    GPIO.add_event_detect(BTN_PIN, GPIO.FALLING, callback=changeLevel, bouncetime=300)
    
  8. Definisce il ciclo main() per:

    • Monitorare la variazione di temperatura rispetto al valore di riferimento,

    • Diminuire la velocità se la temperatura scende di almeno 2°C,

    • Aumentare la velocità se la temperatura sale di almeno 2°C,

    • Regolare la velocità del motore ogni 0,2 secondi.

    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)
    
  9. Avvia la funzione principale e garantisce la chiusura corretta con Ctrl+C (ferma il motore, ripulisce i GPIO, chiude la SPI).

    try:
        main()
    except KeyboardInterrupt:
        pass
    finally:
        pwm.stop()
        GPIO.cleanup()
        spi.close()