.. note::
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 [|link_sf_facebook|] e unisciti oggi stesso!
.. _2.1.7_py_mcp3008:
2.1.7 Potenziometro (MCP3008)
=============================
.. note::
.. image:: ../img/mcp3008_and_adc0834.jpg
:width: 25%
:align: left
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.
.. image:: ../img/list2_2.1.4_potentiometer.png
È sicuramente conveniente acquistare un kit completo, ecco il link:
.. list-table::
:widths: 20 20 20
:header-rows: 1
* - Nome
- ARTICOLI IN QUESTO KIT
- LINK
* - Raphael Kit
- 337
- |link_Raphael_kit|
Puoi anche acquistarli separatamente dai link sottostanti.
.. list-table::
:widths: 30 20
:header-rows: 1
* - INTRODUZIONE COMPONENTE
- LINK DI ACQUISTO
* - :ref:`cpn_gpio_extension_board`
- |link_gpio_board_buy|
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_led`
- |link_led_buy|
* - :ref:`cpn_potentiometer`
- |link_potentiometer_buy|
* - :ref:`cpn_mcp3008`
- \-
Schema elettrico
-----------------
.. list-table::
:widths: 30 30 30 30
:header-rows: 1
* - 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
.. image:: ../img/schematic_2.1.7_potentiometer_mcp3008.png
Procedure sperimentali
-----------------------
**Passo 1:** Costruisci il circuito.
.. image:: ../img/july24_2.1.7_potentiometer_mcp3008.png
.. note::
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 :ref:`spi_configuration` per istruzioni dettagliate). Se hai già completato questi passaggi, puoi saltarli.
**Passo 3:** Apri il file di codice
.. raw:: html
.. code-block::
cd ~/raphael-kit/python
**Passo 4:** Esegui.
.. raw:: html
.. code-block::
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.
.. warning::
Se compare l'errore ``RuntimeError: Cannot determine SOC peripheral base address``, fai riferimento a :ref:`faq_soc`
**Codice**
.. note::
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.
.. raw:: html
.. code-block:: python
#!/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**
#. ``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.
.. code-block:: python
#!/usr/bin/env python3
import spidev
import time
import RPi.GPIO as GPIO
#. Configura il pin GPIO 22 per l'uscita PWM usando ``RPi.GPIO``. Imposta la comunicazione SPI con MCP3008 (Bus 0, CE0) a 1 MHz.
.. code-block:: python
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
#. 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.
.. code-block:: python
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
#. 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.
.. code-block:: python
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
#. 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.
.. code-block:: python
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()