Nota

¡Hola! Bienvenido a la comunidad de entusiastas de SunFounder Raspberry Pi, Arduino y ESP32 en Facebook. Profundiza en Raspberry Pi, Arduino y ESP32 junto con otros aficionados.

¿Por qué unirse?

  • Soporte experto: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.

  • Aprender y compartir: Intercambia consejos y tutoriales para mejorar tus habilidades.

  • Avances exclusivos: Obtén acceso anticipado a anuncios y vistas previas de nuevos productos.

  • Descuentos especiales: Disfruta de descuentos exclusivos en nuestros productos más recientes.

  • Promociones y sorteos festivos: Participa en sorteos y promociones de temporada.

👉 ¿Listo para explorar y crear con nosotros? Haz clic en [Aquí] y únete hoy.

2.2.2 Termistor (MCP3008)

Nota

_images/mcp3008_and_adc0834.jpg

Dependiendo de la versión de tu kit, identifica si tienes ADC0834 o MCP3008 y sigue la sección correspondiente.

Introducción

Al igual que un fotorresistor puede detectar la luz, un termistor es un dispositivo electrónico sensible a la temperatura que puede usarse para funciones de control de temperatura, como crear una alarma de calor.

Componentes requeridos

En este proyecto, necesitamos los siguientes componentes.

_images/list2_2.2.2_thermistor.png

Principio

Un termistor es una resistencia sensible a la temperatura que presenta un cambio preciso y predecible en su resistencia proporcional a pequeños cambios de temperatura. Cuánto cambia su resistencia depende de su composición única. Los termistores pertenecen a un grupo más grande de componentes pasivos. A diferencia de sus contrapartes activas, los dispositivos pasivos no pueden proporcionar ganancia de potencia ni amplificación a un circuito.

El termistor es un elemento sensible y existen dos tipos: coeficiente de temperatura negativo (NTC) y coeficiente de temperatura positivo (PTC). En un PTC la resistencia aumenta con la temperatura, mientras que en un NTC ocurre lo contrario. En este experimento usamos un NTC.

_images/image325.png

El principio es que la resistencia del termistor NTC cambia con la temperatura del ambiente. Cuando la temperatura sube, la resistencia del termistor disminuye. Luego, el voltaje se convierte a valores digitales mediante el adaptador A/D, y la temperatura en Celsius o Fahrenheit se calcula mediante programación.

En este experimento se usa un termistor con una resistencia de referencia de 10 kΩ a 25 °C, junto con una resistencia de pull-up de 10 kΩ.

La relación entre resistencia y temperatura es:

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

  • RT es la resistencia del termistor NTC a la temperatura TK.

  • RN es la resistencia del NTC a la temperatura nominal TN. Aquí, RN = 10 kΩ.

  • TK es la temperatura en Kelvin (K = °C + 273.15).

  • TN es la temperatura nominal en Kelvin (298.15 K para 25 °C).

  • B es la constante del material del NTC (3950 en este caso).

exp significa exponencial y su base e es ≈ 2.7.

Si despejamos, obtenemos: TK= 1 / (ln(RT/RN)/B + 1/TN)

Para Celsius: °C = TK – 273.15.

Este es un modelo empírico válido solo dentro del rango especificado.

Diagrama esquemático

Nombre en la T-Board

Físico

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

Procedimiento experimental

Paso 1: Construye el circuito.

_images/july24_2.2.2_thermistor_mcp3008.png

Para usuarios de C

Paso 2: Ve a la carpeta del código.

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

Paso 3: Compila el código.

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

Nota

-lm es para enlazar la librería matemática. No omitir, o dará error.

Paso 4: Ejecuta el archivo compilado.

./Thermistor

Al ejecutarse, el termistor mide la temperatura ambiente y el programa imprime el valor calculado en pantalla.

Nota

Si no funciona o aparece el error «wiringPi.h: No such file or directory», consulta Instalar y Comprobar WiringPi.

Código

#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 de inicio
    buffer[1] = (8 + channel) << 4;  // Modo unipolar + canal
    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("¡Error al iniciar wiringPi!\n");
        return 1;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("¡Error al configurar SPI!\n");
        return 1;
    }

    while (1) {
        analogVal = read_ADC(0);  // Leer de CH0

        // MCP3008 es ADC de 10 bits (0–1023)
        Vr = 3.3 * analogVal / 1023.0;  // Vref = 3.3V
        Rt = 10000.0 * Vr / (3.3 - Vr); // Divisor de tensión
        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;
}

Explicación del código

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

Estos archivos de cabecera incluyen bibliotecas para el control de GPIO (wiringPi.h), comunicación SPI (wiringPiSPI.h), operaciones de E/S estándar (stdio.h) y funciones matemáticas (math.h) en C.

#define SPI_CHANNEL 0
#define SPI_SPEED   1000000

Define constantes para el canal SPI y la velocidad de comunicación SPI. Aquí se utiliza el canal SPI 0 (CE0) y una velocidad de reloj de 1 MHz.

int read_ADC(int channel)

Esta función lee datos analógicos de un canal específico del ADC MCP3008.

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

Estas líneas formatean el comando SPI de acuerdo con el protocolo del MCP3008: un bit de inicio, configuración para modo de entrada simple (single-ended) y el número de canal.

wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

Transfiere el comando SPI y recibe los datos de 10 bits del ADC MCP3008.

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

Extrae y combina el resultado de 10 bits del ADC a partir del búfer SPI devuelto.

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

Estas líneas inicializan WiringPi y configuran el SPI. Si la inicialización falla, el programa termina.

analogVal = read_ADC(0);

Lee la señal analógica del canal 0 del MCP3008, donde está conectado el divisor de tensión del termistor.

Vr = 3.3 * analogVal / 1023.0;

Convierte el valor digital del ADC en un voltaje analógico. El rango del ADC es 0–1023 con una tensión de referencia de 3,3 V.

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

Calcula la resistencia del termistor usando la fórmula del divisor de tensión. Se asume una resistencia de 10 kΩ en serie con el termistor.

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

Usa la ecuación del parámetro B (B-parameter equation) para convertir la resistencia del termistor a temperatura en Kelvin.

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

cel = temp - 273.15;

Convierte la temperatura de Kelvin a grados Celsius.

Fah = cel * 1.8 + 32;

Convierte la temperatura en Celsius a Fahrenheit.

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

Muestra la temperatura en Celsius y Fahrenheit en la terminal con 2 decimales de precisión.

Para usuarios de Python

Paso 2: Configura la interfaz SPI e instala spidev (ver Configuración de SPI). Si ya lo hiciste, sáltalo.

Paso 3: Ve a la carpeta del código.

cd ~/davinci-kit-for-raspberry-pi/python

Paso 4: Ejecuta el archivo.

sudo python3 2.2.2-2_thermistor.py

Al ejecutarse, el termistor mide la temperatura ambiente y muestra el valor calculado.

Advertencia

Si aparece el error RuntimeError: Cannot determine SOC peripheral base address, consulta Si gpiozero no funciona..

Código

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

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

GPIO.setmode(GPIO.BCM)

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000

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

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)
except KeyboardInterrupt:
    pass
finally:
    spi.close()
    GPIO.cleanup()

Explicación del código

  1. Esta sección importa las bibliotecas necesarias:

    • spidev para la comunicación SPI con el MCP3008

    • time para funciones de retardo

    • math para operaciones logarítmicas en la fórmula de temperatura de Steinhart–Hart

    • RPi.GPIO para inicializar y limpiar los GPIO (incluido por completitud estructural)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import spidev
    import time
    import math
    import RPi.GPIO as GPIO
    
  2. Inicializa el modo GPIO como BCM y configura la interfaz SPI en el bus 0 y dispositivo 0 (CE0), con una velocidad de 1 MHz.

    # Configurar modo GPIO
    GPIO.setmode(GPIO.BCM)
    
    # Inicializar SPI para MCP3008 (Bus 0, CE0)
    spi = spidev.SpiDev()
    spi.open(0, 0)  # Bus 0, Dispositivo 0 (CE0)
    spi.max_speed_hz = 1000000  # 1 MHz
    
  3. Define una función read_adc(channel) para leer valores analógicos de un canal específico (0–7) del MCP3008. Envía un comando SPI de 3 bytes y recibe un resultado analógico de 10 bits (0–1023).

    def read_adc(channel):
        """
        Leer valor analógico del canal 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
    
  4. Bucle principal: Lee el voltaje analógico de un termistor en el canal 0, lo convierte en resistencia, y luego usa la ecuación de Steinhart–Hart para estimar la temperatura en Celsius y Fahrenheit. Las lecturas se actualizan cada 0,2 segundos.

    try:
        while True:
            # Leer valor analógico del canal CH0 del MCP3008
            analogVal = read_adc(0)
    
            # Convertir a voltaje (asumiendo referencia de 3,3 V)
            Vr = 3.3 * analogVal / 1023.0
    
            # Calcular resistencia del termistor (R2 en divisor de tensión = 10 kΩ)
            Rt = 10000.0 * Vr / (3.3 - Vr)
    
            # Cálculo Steinhart–Hart
            tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
    
            # Convertir a Celsius y Fahrenheit
            Cel = tempK - 273.15
            Fah = Cel * 1.8 + 32
    
            # Imprimir el resultado
            print('Celsius: %.2f °C  Fahrenheit: %.2f °F' % (Cel, Fah))
    
            time.sleep(0.2)
    
  5. El bloque finally asegura un cierre correcto. Cierra la interfaz SPI y limpia la configuración de GPIO para liberar todos los recursos de hardware.

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