Nota

Ciao, benvenuto nella Community SunFounder per appassionati di Raspberry Pi, Arduino e ESP32 su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad 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 consigli e tutorial per migliorare le tue competenze.

  • Anteprime esclusive: Accedi in anteprima ai nuovi annunci di prodotto e agli sneak peek.

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

  • Promozioni e giveaway festivi: Partecipa a giveaway e promozioni durante le festività.

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

2.2.2 Termistore (MCP3008)

Nota

_images/mcp3008_and_adc0834.jpg

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

Introduzione

Così come la fotoresistenza può rilevare la luce, il termistore è un dispositivo elettronico sensibile alla temperatura che può essere utilizzato per realizzare funzioni di controllo della temperatura, come la creazione di un allarme di calore.

Componenti richiesti

In questo progetto, abbiamo bisogno dei seguenti componenti.

_images/list2_2.2.2_thermistor.png

Principio

Un termistore è una resistenza sensibile alla temperatura che mostra una variazione precisa e prevedibile della resistenza proporzionale a piccoli cambiamenti di temperatura. L’entità della variazione di resistenza dipende dalla sua composizione unica. I termistori fanno parte di un gruppo più ampio di componenti passivi. A differenza dei loro omologhi attivi, i dispositivi passivi non sono in grado di fornire guadagno di potenza o amplificazione a un circuito.

Il termistore è un elemento sensibile e ne esistono due tipi: coefficiente di temperatura negativo (NTC) e coefficiente di temperatura positivo (PTC), conosciuti anche come NTC e PTC. La sua resistenza varia in modo significativo con la temperatura. La resistenza del termistore PTC aumenta con la temperatura, mentre per l’NTC avviene l’opposto. In questo esperimento utilizziamo un NTC.

_images/image325.png

Il principio è che la resistenza del termistore NTC varia con la temperatura dell’ambiente esterno. Rileva la temperatura in tempo reale dell’ambiente. Quando la temperatura aumenta, la resistenza del termistore diminuisce. Successivamente i dati di tensione vengono convertiti in valori digitali dall’adattatore A/D. La temperatura in gradi Celsius o Fahrenheit viene quindi restituita tramite programmazione.

In questo esperimento si utilizza un termistore e una resistenza di pull-up da 10k. Ogni termistore ha una resistenza nominale; in questo caso è di 10k ohm, misurata a 25 °C.

Ecco la relazione tra resistenza e temperatura:

RT = RN expB(1/TK – 1/TN)

RT è la resistenza del termistore NTC alla temperatura TK.

RN è la resistenza del termistore NTC alla temperatura nominale TN. Qui il valore di RN è 10k.

TK è una temperatura Kelvin, l’unità è K. Qui il valore di TK è 273,15 + gradi Celsius.

TN è una temperatura nominale in Kelvin; l’unità è K. Qui il valore di TN è 273,15 + 25.

B (beta), la costante del materiale del termistore NTC, è detta anche indice di sensibilità termica ed è pari a 3950.

exp è l’abbreviazione di esponenziale, e il numero base e è un numero naturale pari a circa 2,7.

Convertendo questa formula TK= 1 / (ln(RT/RN)/B + 1/TN) si ottiene la temperatura Kelvin, che meno 273,15 dà la temperatura in gradi Celsius.

Questa relazione è una formula empirica ed è accurata solo quando temperatura e resistenza rientrano nell’intervallo effettivo.

Schema elettrico

Nome T-Board

fisico

WiringPi

BCM

SPICE0

pin24

10

8

SPIMOSI

pin19

12

10

SPIMISO

pin21

13

9

SPISCLK

pin23

14

11

_images/schematic_2.2.2_thermistor_mcp3008.png

Procedure sperimentali

Passo 1: Costruisci il circuito.

_images/july24_2.2.2_thermistor_mcp3008.png

Per utenti C Language

Passo 2: Vai nella cartella del codice.

cd ~/davinci-kit-for-raspberry-pi/c/2.2.2-2/

Passo 3: Compila il codice.

gcc 2.2.2_Thermistor.c -o Thermistor -lwiringPi -lm

Nota

-lm serve per caricare la libreria matematica. Non ometterlo, o si verificherà un errore.

Passo 4: Esegui il file eseguibile.

./Thermistor

Quando il codice è in esecuzione, il termistore rileva la temperatura ambiente e la stampa sullo schermo una volta completato il calcolo.

Nota

Se non funziona dopo l’esecuzione, o appare l’errore «wiringPi.h: No such file or directory», fare riferimento a Installare e Verificare WiringPi.

Codice

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <math.h>

#define SPI_CHANNEL 0  // CE0
#define SPI_SPEED   1000000  // 1MHz

int read_ADC(int channel) {
    if (channel < 0 || channel > 7) return -1;

    unsigned char buffer[3];
    buffer[0] = 1;  // Bit di avvio
    buffer[1] = (8 + channel) << 4;  // Modalità single-ended + canale
    buffer[2] = 0;

    wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

    int value = ((buffer[1] & 3) << 8) | buffer[2];
    return value;
}

int main(void) {
    int analogVal;
    double Vr, Rt, temp, cel, Fah;

    if (wiringPiSetup() == -1) {
        printf("setup wiringPi fallito!\n");
        return 1;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("configurazione SPI fallita!\n");
        return 1;
    }

    while (1) {
        analogVal = read_ADC(0);  // Legge da CH0

        // MCP3008 è un ADC a 10 bit (0–1023)
        Vr = 3.3 * analogVal / 1023.0;  // Si assume Vref = 3.3V
        Rt = 10000.0 * Vr / (3.3 - Vr); // Partitore di tensione, resistenza 10k
        temp = 1 / ((log(Rt / 10000.0) / 3950.0) + (1 / (273.15 + 25.0)));
        cel = temp - 273.15;
        Fah = cel * 1.8 + 32;

        printf("Celsius: %.2f C  Fahrenheit: %.2f F\n", cel, Fah);
        delay(1000);
    }

    return 0;
}

Spiegazione del codice

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <math.h>

Questi file di intestazione includono le librerie per il controllo GPIO (wiringPi.h), la comunicazione SPI (wiringPiSPI.h), le operazioni di I/O standard (stdio.h) e le funzioni matematiche (math.h) in C.

#define SPI_CHANNEL 0
#define SPI_SPEED   1000000

Definiscono costanti per il canale SPI e la velocità di comunicazione SPI. Qui si usa il canale SPI 0 (CE0) e una frequenza di clock di 1 MHz.

int read_ADC(int channel)

Questa funzione legge dati analogici da un canale specificato dell’ADC MCP3008.

buffer[0] = 1;
buffer[1] = (8 + channel) << 4;
buffer[2] = 0;

Queste righe formattano il comando SPI secondo il protocollo MCP3008: un bit di avvio, configurazione per la modalità single-ended e il numero di canale.

wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

Trasmette il comando SPI e riceve i dati ADC a 10 bit dal MCP3008.

int value = ((buffer[1] & 3) << 8) | buffer[2];

Estrae e combina il risultato ADC a 10 bit dal buffer SPI ricevuto.

if (wiringPiSetup() == -1) { ... }
if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) { ... }

Queste righe inizializzano WiringPi e configurano l’SPI. Se l’inizializzazione fallisce, il programma termina.

analogVal = read_ADC(0);

Legge il segnale analogico dal canale 0 del MCP3008, dove è collegato il partitore di tensione del termistore.

Vr = 3.3 * analogVal / 1023.0;

Converte il valore digitale ADC in tensione analogica. L’ADC ha un intervallo 0–1023 con tensione di riferimento di 3,3V.

Rt = 10000.0 * Vr / (3.3 - Vr);

Calcola la resistenza del termistore utilizzando la formula del partitore di tensione. Si assume una resistenza in serie da 10kΩ.

temp = 1 / ((log(Rt / 10000.0) / 3950.0) + (1 / (273.15 + 25.0)));

Usa l’equazione del parametro B per convertire la resistenza del termistore in temperatura Kelvin.

T(K) = 1 / [ln(Rt/R₀)/B + 1/T₀], dove - R₀ = 10kΩ - B = 3950 - T₀ = 25°C = 298,15K

cel = temp - 273.15;

Converte la temperatura da Kelvin a gradi Celsius.

Fah = cel * 1.8 + 32;

Converte la temperatura in Celsius a Fahrenheit.

printf("Celsius: %.2f C  Fahrenheit: %.2f F\n", cel, Fah);

Visualizza la temperatura sia in Celsius che in Fahrenheit sul terminale con due decimali di precisione.

Per utenti Python

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 ~/davinci-kit-for-raspberry-pi/python

Passo 4: Esegui il file

sudo python3 2.2.2-2_thermistor.py

Quando il codice è in esecuzione, il termistore rileva la temperatura ambiente e la stampa sullo schermo una volta completato il calcolo.

Avvertimento

Se appare l’errore RuntimeError: Cannot determine SOC peripheral base address, fare riferimento a Se gpiozero non funziona.

Codice

Nota

Puoi Modificare/Reimpostare/Copiare/Eseguire/Interrompere il codice qui sotto. Ma prima devi andare nel percorso del codice sorgente come davinci-kit-for-raspberry-pi/python. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

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

# Imposta la modalità GPIO
GPIO.setmode(GPIO.BCM)

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

def read_adc(channel):
    """
    Legge il valore analogico dal canale MCP3008 (0–7)
    """
    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

try:
    while True:
        # Legge il valore analogico dal CH0 di MCP3008
        analogVal = read_adc(0)

        # Converte in tensione (si assume 3,3V di riferimento)
        Vr = 3.3 * analogVal / 1023.0

        # Calcola la resistenza del termistore (R2 nel partitore è 10kΩ)
        Rt = 10000.0 * Vr / (3.3 - Vr)

        # Calcolo Steinhart–Hart
        tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))

        # Conversione in Celsius e Fahrenheit
        Cel = tempK - 273.15
        Fah = Cel * 1.8 + 32

        # Stampa il risultato
        print('Celsius: %.2f °C  Fahrenheit: %.2f °F' % (Cel, Fah))

        time.sleep(0.2)

except KeyboardInterrupt:
    pass

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

Spiegazione del codice

  1. Questa sezione importa le librerie richieste:

    • spidev per la comunicazione SPI con MCP3008

    • time per la gestione delle pause

    • math per operazioni logaritmiche nella formula Steinhart–Hart

    • RPi.GPIO per inizializzare e pulire i GPIO (incluso per completezza strutturale)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import spidev
    import time
    import math
    import RPi.GPIO as GPIO
    
  2. Inizializza la modalità GPIO come BCM e configura l’interfaccia SPI sul bus 0 e dispositivo 0 (CE0), con una velocità di 1 MHz.

    GPIO.setmode(GPIO.BCM)
    spi = spidev.SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    
  3. Definisce la funzione read_adc(channel) per leggere i valori analogici da un canale MCP3008 (0–7). Invia un comando SPI di 3 byte e riceve un risultato analogico a 10 bit (0–1023).

    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
    
  4. Ciclo principale: legge la tensione analogica dal termistore sul canale 0, la converte in resistenza e poi usa l’equazione di Steinhart–Hart per stimare la temperatura in Celsius e Fahrenheit. Aggiorna i dati ogni 0,2 secondi.

    try:
        while True:
            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
            Fah = Cel * 1.8 + 32
            print('Celsius: %.2f °C  Fahrenheit: %.2f °F' % (Cel, Fah))
            time.sleep(0.2)
    
  5. Il blocco finally garantisce una chiusura ordinata: chiude l’interfaccia SPI e rilascia tutte le risorse hardware.

    except KeyboardInterrupt:
        pass
    
    finally:
        spi.close()
        GPIO.cleanup()