.. note:: ¡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 [|link_sf_facebook|] y únete hoy mismo. .. _3.1.8_c_mcp3008: 3.1.8 Monitor de sobrecalentamiento (MCP3008) ============================================= .. note:: .. image:: img/mcp3008_and_adc0834.jpg :width: 25% :align: left 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. .. image:: img/list2_Overheat_Monitor.png :align: center 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 ============ ======== ======== === .. image:: img/Schematic_three_one8.png :align: center Procedimiento experimental -------------------------- **Paso 1:** Monta el circuito. .. image:: img/july24_3.1.8_overheat_monitor_mcp3008.png **Para usuarios de lenguaje C** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Paso 2**: Ve a la carpeta del código. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/3.1.8-2/ **Paso 3**: Compila el código. .. raw:: html .. code-block:: gcc 3.1.8_OverheatMonitor.c -lm -lwiringPi **Paso 4**: Ejecuta el archivo compilado. .. raw:: html .. code-block:: 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. .. note:: * Si aparece el error ``wiringPi.h: No such file or directory``, consulta :ref:`install_wiringpi`. * Si aparece el error ``Unable to open I2C device: No such file or directory``, consulta :ref:`i2c_config` 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 ---------------------- .. code-block:: c 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. .. code-block:: c 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. .. code-block:: c 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. .. code-block:: c 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. .. code-block:: c 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. .. code-block:: c 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. .. code-block:: c 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. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Paso 4**: Ejecuta el archivo ejecutable. .. raw:: html .. code-block:: 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. .. note:: * Si aparece el error ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, debes consultar :ref:`i2c_config` 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. .. warning:: Si aparece el error ``RuntimeError: Cannot determine SOC peripheral base address``, consulta :ref:`faq_soc` **Código** .. note:: 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. .. raw:: html .. code-block:: python #!/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. .. code-block:: python #!/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. .. code-block:: python 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. .. code-block:: python 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. .. 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] & 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. .. code-block:: python 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. .. code-block:: python 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. .. code-block:: python 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. .. code-block:: python 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. .. code-block:: python 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. .. code-block:: python except KeyboardInterrupt: pass finally: LCD1602.clear() GPIO.cleanup() spi.close()