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!

2.1.7 Potenziometro (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

La funzione ADC viene utilizzata per convertire segnali analogici in valori digitali. In questo esperimento, utilizziamo il chip ADC MCP3008 per effettuare questa conversione. Un potenziometro viene utilizzato per generare una tensione variabile, che cambia la quantità fisica. Il MCP3008 converte quindi questa tensione analogica in un valore digitale che può essere letto ed elaborato dal Raspberry Pi.

Componenti richiesti

In questo progetto, ci servono i seguenti componenti.

../_images/list2_2.1.4_potentiometer.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

LED

ACQUISTA

Potenziometro

ACQUISTA

MCP3008

-

Schema elettrico

Nome T-Board

fisico

WiringPi

BCM

SPICE0

pin24

10

8

SPIMOSI

pin19

12

10

SPIMISO

pin21

13

9

SPISCLK

pin23

14

11

GPIO22

pin15

3

22

../_images/schematic_2.1.7_potentiometer_mcp3008.png

Procedure sperimentali

Passo 1: Costruisci il circuito.

../_images/july24_2.1.7_potentiometer_mcp3008.png

Nota

Posiziona il chip facendo riferimento alla posizione corrispondente mostrata nell’immagine. Nota che le scanalature sul chip devono essere rivolte a sinistra quando viene posizionato.

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: Apri il file di codice

cd ~/raphael-kit/python

Passo 4: Esegui.

sudo python3 2.1.7-2_Potentiometer.py

Dopo l’esecuzione del codice, ruota la manopola del potenziometro, l’intensità del LED cambierà di conseguenza.

Avvertimento

Se compare l’errore RuntimeError: Cannot determine SOC peripheral base address, fai riferimento a If gpiozero doesn’t work.

Codice

Nota

Puoi Modificare/Resettare/Copiare/Eseguire/Fermare il codice qui sotto. Ma prima devi andare al 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 spidev
import time
import RPi.GPIO as GPIO

# Pin GPIO per uscita PWM
PWM_PIN = 22

# Configurazione GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(PWM_PIN, GPIO.OUT)

# Inizializza PWM su GPIO22 a 1000Hz
pwm = GPIO.PWM(PWM_PIN, 1000)
pwm.start(0)  # Avvia con duty cycle 0%

# Inizializza SPI
spi = spidev.SpiDev()
spi.open(0, 0)  # Bus 0, CE0
spi.max_speed_hz = 1000000

def read_adc(channel):
    """
    Legge il valore analogico da MCP3008
    :param channel: canale ADC (0-7)
    :return: valore intero a 10 bit (0-1023)
    """
    if channel < 0 or channel > 7:
        return -1
    adc = spi.xfer2([1, (8 + channel) << 4, 0])
    value = ((adc[1] & 3) << 8) | adc[2]
    return value

def MAP(x, in_min, in_max, out_min, out_max):
    """
    Mappa un valore da un intervallo a un altro
    """
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

try:
    while True:
        # Leggi valore analogico da CH0
        res = read_adc(0)
        print('res = %d' % res)

        # Converte in duty cycle 0–100%
        duty_cycle = MAP(res, 0, 1023, 0, 100)

        # Aggiorna duty cycle PWM
        pwm.ChangeDutyCycle(duty_cycle)

        time.sleep(0.2)

except KeyboardInterrupt:
    pass

finally:
    pwm.stop()
    GPIO.cleanup()
    spi.close()

Spiegazione del codice

  1. RPi.GPIO viene utilizzato per generare segnali PWM per controllare un LED. spidev viene utilizzato per la comunicazione SPI con MCP3008. time viene utilizzato per aggiungere ritardi nel ciclo.

    #!/usr/bin/env python3
    
    import spidev
    import time
    import RPi.GPIO as GPIO
    
  2. Configura il pin GPIO 22 per l’uscita PWM usando RPi.GPIO. Imposta la comunicazione SPI con MCP3008 (Bus 0, CE0) a 1 MHz.

    PWM_PIN = 22
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PWM_PIN, GPIO.OUT)
    
    pwm = GPIO.PWM(PWM_PIN, 1000)  # frequenza 1kHz
    pwm.start(0)  # Avvia con duty cycle 0%
    
    spi = spidev.SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    
  3. Questa funzione legge i dati analogici dal MCP3008 sul canale specificato (0–7) usando il protocollo SPI. Il risultato è un intero a 10 bit compreso tra 0 e 1023.

    def read_adc(channel):
        if channel < 0 or channel > 7:
            return -1
        adc = spi.xfer2([1, (8 + channel) << 4, 0])
        value = ((adc[1] & 3) << 8) | adc[2]
        return value
    
  4. Questa funzione mappa un valore da un intervallo numerico a un altro. Viene utilizzata per scalare i valori ADC in percentuali di duty cycle PWM.

    def MAP(x, in_min, in_max, out_min, out_max):
        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
    
  5. Nel ciclo principale, il programma legge continuamente i dati analogici dal canale 0 del MCP3008, mappa il valore su un intervallo PWM (0–100) e imposta di conseguenza la luminosità del LED. Il ciclo si aggiorna ogni 0,2 secondi. Se interrotto (ad esempio con Ctrl+C), il programma ferma il segnale PWM e ripristina la configurazione GPIO.

    try:
        while True:
            res = read_adc(0)
            print('res = %d' % res)
    
            duty_cycle = MAP(res, 0, 1023, 0, 100)
            pwm.ChangeDutyCycle(duty_cycle)
    
            time.sleep(0.2)
    
    except KeyboardInterrupt:
        pass
    
    finally:
        pwm.stop()
        GPIO.cleanup()
        spi.close()