Nota

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

¿Por qué unirse?

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

  • Aprende y comparte: Intercambia consejos y tutoriales para mejorar tus habilidades.

  • Vistas previas exclusivas: Obtén acceso anticipado a nuevos anuncios de productos y adelantos.

  • 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 mismo.

3.1.8 Monitor de sobrecalentamiento (MCP3008)

Nota

_images/mcp3008_and_adc0834.jpg

Dependiendo de la versión de tu kit, identifica si tienes ADC0834 o MCP3008 y continúa con la sección correspondiente.

Introducción

Puede que desees crear un dispositivo de monitoreo de sobrecalentamiento aplicable a diversas situaciones. Por ejemplo, en una fábrica, si queremos tener una alarma y apagado automático cuando un circuito se sobrecalienta. En este proyecto utilizaremos un termistor, un joystick, un zumbador, un LED y una pantalla LCD para fabricar un dispositivo inteligente de monitoreo de temperatura cuyo umbral es ajustable.

Componentes necesarios

En este proyecto, necesitamos los siguientes componentes.

_images/list2_Overheat_Monitor.png

Diagrama esquemático

T-Board Name

físico

wiringPi

BCM

SPICE0

Pin 24

10

8

SPIMOSI

Pin 19

12

10

SPIMISO

Pin 21

13

9

SPISCLK

Pin 23

14

11

GPIO22

Pin15

3

22

GPIO23

Pin16

4

23

GPIO24

Pin18

5

24

SDA1

Pin 3

SCL1

Pin 5

_images/Schematic_three_one8.png

Procedimiento experimental

Paso 1: Monta el circuito.

_images/july24_3.1.8_overheat_monitor_mcp3008.png

Para usuarios de lenguaje C

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

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

Paso 3: Compila el código.

gcc 3.1.8_OverheatMonitor.c -lm -lwiringPi

Paso 4: Ejecuta el archivo compilado.

sudo ./a.out

Cuando se ejecute el código, la temperatura actual y el umbral de alta temperatura 40 se mostrarán en la I2C LCD1602. Si la temperatura actual es mayor que el umbral, el zumbador y el LED se activarán para alertarte.

El joystick sirve para ajustar el umbral de alta temperatura. Moviendo el joystick en el eje X o Y podrás aumentar o disminuir el umbral. Pulsando el joystick nuevamente lo restablecerás a su valor inicial.

Nota

  • Si aparece el error wiringPi.h: No such file or directory, consulta Instalar y Comprobar WiringPi.

  • Si aparece el error Unable to open I2C device: No such file or directory, consulta Configuración de I²C para habilitar I2C y verificar el cableado.

  • Si el código y el cableado están correctos pero la LCD no muestra nada, ajusta el potenciómetro en la parte trasera para aumentar el contraste.

Explicación del código

int read_ADC(int channel) {
    if (channel < 0 || channel > 7) return -1;
    unsigned char buffer[3];
    buffer[0] = 1;
    buffer[1] = (8 + channel) << 4;
    buffer[2] = 0;
    wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
    return ((buffer[1] & 0x03) << 8) | buffer[2];
}

Lee un valor analógico de 10 bits desde el canal MCP3008 (CH0–CH7) usando SPI y devuelve un entero de 0 a 1023.

int get_joystick_value() {
    int x = read_ADC(1);
    int y = read_ADC(2);

    if (x > 900)      return 1;   // Derecha
    else if (x < 100) return -1;  // Izquierda
    else if (y > 900) return -10; // Arriba
    else if (y < 100) return 10;  // Abajo
    else              return 0;
}

Lee los valores analógicos X e Y del joystick desde CH1 y CH2. Devuelve un número indicando la dirección según los umbrales.

void upper_tem_setting() {
    write_lcd(0,0, "Upper Adjust:");

    int change = get_joystick_value();

    if (change != 0 && change != lastJoystickChange) {
        upperTem += change;
        lastJoystickChange = change;
    }
    else if (change == 0) {
        lastJoystickChange = 0;
    }

    char str[6];
    snprintf(str, sizeof(str), "%d", upperTem);
    write_lcd(0,1, str);
    write_lcd(strlen(str),1, "            ");

    delay(100);
}

Permite ajustar el umbral de temperatura usando el joystick. Evita cambios repetidos cuando se mantiene la dirección.

double temperature() {
    int raw = read_ADC(0);
    double Vr = 3.3 * ((double)raw / 1023.0);
    double Rt = 10000.0 * Vr / (3.3 - Vr);
    double tempK = 1.0 / ((log(Rt/10000.0)/3950.0) + 1.0/(273.15+25.0));
    return tempK - 273.15;
}

Lee el valor analógico desde CH0 conectado al termistor y usa la ecuación de Steinhart–Hart para calcular la temperatura en grados Celsius.

void monitoring_temp() {
    char str[6];
    double cel = temperature();
    snprintf(str, sizeof(str), "%.2f", cel);
    write_lcd(0,0, "Temp: ");
    write_lcd(6,0, str);

    snprintf(str, sizeof(str), "%d", upperTem);
    write_lcd(0,1, "Upper: ");
    write_lcd(7,1, str);
    delay(100);

    if (cel >= upperTem) {
        digitalWrite(buzzPin, HIGH);
        digitalWrite(LedPin,  HIGH);
    } else {
        digitalWrite(buzzPin, LOW);
        digitalWrite(LedPin,  LOW);
    }
}

Lee continuamente la temperatura y la muestra junto con el umbral. Si la temperatura supera el umbral, activa el zumbador y el LED.

void setup_all() {
    fd = wiringPiI2CSetup(LCDAddr);
    lcd_init();
    if (wiringPiSetup() == -1 || wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("Setup failed!\n");
        return;
    }
    pinMode(Joy_BtnPin, INPUT);
    pullUpDnControl(Joy_BtnPin, PUD_UP);
    pinMode(buzzPin, OUTPUT);
    pinMode(LedPin,  OUTPUT);
}

Inicializa la LCD, SPI y los pines GPIO para el botón del joystick, el zumbador y el LED. Activa la resistencia pull-up para el botón del joystick.

int main(void) {
    setup_all();

    int lastBtnState = HIGH;
    int stage = 0;

    while (1) {
        int curBtn = digitalRead(Joy_BtnPin);
        if (curBtn == HIGH && lastBtnState == LOW) {
            stage = (stage + 1) % 2;
            lastJoystickChange = 0;
            delay(100);
            lcd_clear();
        }
        lastBtnState = curBtn;

        if (stage == 1)
            upper_tem_setting();
        else
            monitoring_temp();
    }

    return 0;
}

El bucle principal alterna entre dos modos:

  1. Monitoreo de temperatura.

  2. Ajuste del límite máximo usando el joystick.

El cambio de modo ocurre cuando se suelta el botón del joystick (detecto de flanco ascendente).

Para usuarios del lenguaje Python

Paso 2: Configura la interfaz SPI e instala la biblioteca spidev (consulta :ref:spi_configuration para obtener instrucciones detalladas). Si ya has completado estos pasos, puedes omitir este.

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

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

Paso 4: Ejecuta el archivo ejecutable.

sudo python3 3.1.8-2_OverheatMonitor.py

Mientras el código se ejecuta, la temperatura actual y el umbral de alta temperatura 40 se muestran en I2C LCD1602. Si la temperatura actual es mayor que el umbral, el zumbador y el LED comenzarán a alertarte.

El Joystick sirve para que, al presionarlo, puedas ajustar el umbral de alta temperatura. Moviendo el Joystick en la dirección del eje X o Y se puede ajustar (subir o bajar) el umbral actual de alta temperatura. Presiona el Joystick nuevamente para restablecer el umbral a su valor inicial.

Nota

  • Si aparece el error FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1', debes consultar Configuración de I²C para habilitar el I2C.

  • Si aparece el error ModuleNotFoundError: No module named 'smbus2', ejecuta sudo pip3 install smbus2.

  • Si aparece el error OSError: [Errno 121] Remote I/O error, significa que el módulo está mal cableado o dañado.

  • Si el código y el cableado están bien, pero la LCD aún no muestra contenido, gira el potenciómetro en la parte trasera para aumentar el contraste.

Advertencia

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

Código

Nota

Puedes Modificar/Restablecer/Copiar/Ejecutar/Detener el código a continuación. Pero antes de eso, debes ir a la ruta del código fuente como davinci-kit-for-raspberry-pi/python. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto.

#!/usr/bin/env python3

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

# Definición de pines GPIO
JOY_BTN_PIN = 22  # Pin del botón
BUZZER_PIN = 23   # Pin del zumbador
LED_PIN = 24      # Pin del LED

# Inicializar GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(JOY_BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)

# Umbral inicial de temperatura alta
upperTem = 40

# Inicializar SPI para MCP3008
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000  # 1 MHz

# Inicializar LCD1602
LCD1602.init(0x27, 1)

def read_adc(channel):
   """
   Lee el valor analógico del 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

def get_joystick_value():
   """
   Lee los valores del joystick y devuelve un cambio basado en su posición.
   """
   x_val = read_adc(1)
   y_val = read_adc(2)
   if x_val > 800:
      return 1
   elif x_val < 200:
      return -1
   elif y_val > 800:
      return -10
   elif y_val < 200:
      return 10
   else:
      return 0

def upper_tem_setting():
   """
   Ajusta y muestra el umbral de temperatura alta en la LCD.
   """
   global upperTem
   LCD1602.write(0, 0, 'Upper Adjust: ')
   change = int(get_joystick_value())
   upperTem += change
   strUpperTem = str(upperTem)
   LCD1602.write(0, 1, strUpperTem)
   LCD1602.write(len(strUpperTem), 1, '              ')
   time.sleep(0.1)

def temperature():
   """
   Lee la temperatura actual del sensor y la devuelve en grados Celsius.
   """
   analogVal = read_adc(0)
   Vr = 3.3 * analogVal / 1023.0
   if Vr == 0:
      return 0
   Rt = 10000.0 * (3.3 - Vr) / Vr
   tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
   Cel = tempK - 273.15
   return round(Cel, 2)

def monitoring_temp():
   """
   Supervisa y muestra la temperatura actual y el umbral de temperatura alta.
   Activa el zumbador y el LED si la temperatura supera el límite.
   """
   global upperTem
   Cel = temperature()
   LCD1602.write(0, 0, 'Temp: ')
   LCD1602.write(0, 1, 'Upper: ')
   LCD1602.write(6, 0, str(Cel))
   LCD1602.write(7, 1, str(upperTem))
   time.sleep(0.1)
   if Cel >= upperTem:
      GPIO.output(BUZZER_PIN, GPIO.HIGH)
      GPIO.output(LED_PIN, GPIO.HIGH)
   else:
      GPIO.output(BUZZER_PIN, GPIO.LOW)
      GPIO.output(LED_PIN, GPIO.LOW)

# Bucle principal
try:
   lastState = GPIO.input(JOY_BTN_PIN)
   stage = 0
   while True:
      currentState = GPIO.input(JOY_BTN_PIN)
      if currentState == GPIO.HIGH and lastState == GPIO.LOW:
            stage = (stage + 1) % 2
            time.sleep(0.1)
            LCD1602.clear()
      lastState = currentState

      if stage == 1:
            upper_tem_setting()
      else:
            monitoring_temp()

except KeyboardInterrupt:
   pass

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

Explicación del código

  1. Importar bibliotecas

    Esta sección carga las bibliotecas necesarias para GPIO, SPI, pantalla LCD, retardos y operaciones matemáticas.

    #!/usr/bin/env python3
    import RPi.GPIO as GPIO
    import spidev
    import time
    import math
    import LCD1602
    
  2. Configuración de GPIO y dispositivos

    Define los números de pines GPIO para el botón del joystick, el zumbador y el LED, y configura los modos GPIO.

    JOY_BTN_PIN = 22  # Pin del botón
    BUZZER_PIN = 23   # Pin del zumbador
    LED_PIN = 24      # Pin del LED
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(JOY_BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(BUZZER_PIN, GPIO.OUT)
    GPIO.setup(LED_PIN, GPIO.OUT)
    
  3. Inicialización de SPI y LCD

    Inicia la interfaz SPI para el MCP3008 e inicializa la pantalla LCD1602 con dirección I2C 0x27.

    upperTem = 40
    spi = spidev.SpiDev()
    spi.open(0, 0)
    spi.max_speed_hz = 1000000
    
    LCD1602.init(0x27, 1)
    
  4. Lectura de valor ADC

    Lee datos analógicos desde el MCP3008 vía SPI. El canal debe estar en el rango de 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. Detección de movimiento del joystick

    Verifica los valores de los ejes X/Y del joystick y devuelve cuánto debe cambiar el umbral.

    def get_joystick_value():
       x_val = read_adc(1)
       y_val = read_adc(2)
       if x_val > 800:
          return 1
       elif x_val < 200:
          return -1
       elif y_val > 800:
          return -10
       elif y_val < 200:
          return 10
       else:
          return 0
    
  6. Ajuste del umbral de temperatura alta

    Muestra «Upper Adjust» en la LCD y ajusta el umbral usando el joystick.

    def upper_tem_setting():
       global upperTem
       LCD1602.write(0, 0, 'Upper Adjust: ')
       change = int(get_joystick_value())
       upperTem += change
       strUpperTem = str(upperTem)
       LCD1602.write(0, 1, strUpperTem)
       LCD1602.write(len(strUpperTem), 1, '              ')
       time.sleep(0.1)
    
  7. Cálculo de la temperatura

    Convierte la lectura del sensor en voltaje, resistencia y finalmente en grados Celsius usando la aproximación de Steinhart–Hart.

    def temperature():
       analogVal = read_adc(0)
       Vr = 3.3 * analogVal / 1023.0
       if Vr == 0:
          return 0
       Rt = 10000.0 * (3.3 - Vr) / Vr
       tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
       Cel = tempK - 273.15
       return round(Cel, 2)
    
  8. Monitoreo de temperatura

    Comprueba y muestra continuamente la temperatura y el límite. Activa el zumbador y el LED si la temperatura supera el umbral.

    def monitoring_temp():
       global upperTem
       Cel = temperature()
       LCD1602.write(0, 0, 'Temp: ')
       LCD1602.write(0, 1, 'Upper: ')
       LCD1602.write(6, 0, str(Cel))
       LCD1602.write(7, 1, str(upperTem))
       time.sleep(0.1)
       if Cel >= upperTem:
          GPIO.output(BUZZER_PIN, GPIO.HIGH)
          GPIO.output(LED_PIN, GPIO.HIGH)
       else:
          GPIO.output(BUZZER_PIN, GPIO.LOW)
          GPIO.output(LED_PIN, GPIO.LOW)
    
  9. Lógica principal del programa

    Alterna entre el monitoreo de temperatura y el ajuste de umbral cuando se presiona el botón del joystick.

    try:
       lastState = GPIO.input(JOY_BTN_PIN)
       stage = 0
       while True:
          currentState = GPIO.input(JOY_BTN_PIN)
          if currentState == GPIO.HIGH and lastState == GPIO.LOW:
                stage = (stage + 1) % 2
                time.sleep(0.1)
                LCD1602.clear()
          lastState = currentState
    
          if stage == 1:
                upper_tem_setting()
          else:
                monitoring_temp()
    
  10. Limpieza al salir

    Garantiza la liberación adecuada de recursos GPIO y SPI cuando se presiona Ctrl+C.

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