lunes, 14 de noviembre de 2050

Inicio

Bienvenido al Blog Todoelectrodo!

Este Blog se creo con la finalidad de compartir mis conocimientos y experiencia en electrónica. Espero que encuentres aquí la ayuda que necesites y si no es así, escríbeme y veremos que se puede hacer.

Un saludo!





domingo, 25 de octubre de 2026

ESP8266 y Wemos D1 mini, pequeño micro pero peleón.

ESP8266 y Wemos D1 mini. Un pequeño microcontrolador con WiFi para nuestros proyectos IoT

Bueno, en este post me gustaría hablaros sobre el ESP8266 y, concretamente, sobre la Wemos D1 mini, una pequeña placa que llevo tiempo viendo en multitud de proyectos de electrónica y domótica y que me parece muy interesante por las posibilidades que ofrece.

Muchos ya conoceréis este microcontrolador, pero puede que otros todavía no y ese es precisamente mi objetivo, darlo a conocer y enseñaros algunas de las cosas que podemos hacer con él.

Y es que, aunque actualmente tenemos otras opciones más potentes como el ESP32, el ESP8266 sigue siendo una alternativa muy interesante para un montón de proyectos. Tenemos WiFi integrado, podemos conectar sensores, controlar salidas y comunicarnos con otros dispositivos sin necesidad de añadir módulos externos.

En mi caso vamos a utilizar una Wemos D1 mini, una placa muy pequeña, económica y bastante cómoda para trabajar. Veremos sus características, cómo programarla, cómo leer un sensor analógico y, para terminar, cómo podemos integrarla en nuestro sistema domótico mediante ESPHome y Home Assistant.

Vamos al tomate jaja.

¿Qué es el ESP8266?



Digamos que el ESP8266 es un microcontrolador de 32 bits que incorpora conectividad WiFi. Es decir, tenemos un pequeño dispositivo capaz de ejecutar nuestros propios programas y conectarse a nuestra red inalámbrica sin necesidad de añadir un módulo WiFi externo.

¿Y para qué nos puede servir esto? Pues para muchísimas cosas: controlar luces, leer sensores de temperatura, monitorizar la humedad de una habitación, controlar un relé, montar una estación meteorológica o enviar información a nuestro servidor domótico.

Además, no necesitamos una Raspberry Pi o un Arduino conectado permanentemente para que funcione. Una vez programado, el ESP8266 puede trabajar de forma autónoma, siempre que le proporcionemos una alimentación adecuada.

La gracia de este microcontrolador es que podemos utilizarlo tanto para proyectos sencillos como para montar pequeños dispositivos IoT que se comuniquen con otros sistemas de nuestra red local.

¿¿Y cual es otra de las cosas Importantes?? 

Para lo que nos permite hacer es una placa Muuuuuuy ECONÓMICA.

¿Qué es la Wemos D1 mini?

La Wemos D1 mini es una placa de desarrollo basada en el ESP8266. Existen diferentes versiones y placas compatibles, pero las más habituales incorporan 4 MB de memoria Flash y un conector USB que nos permite alimentarlas y programarlas desde el ordenador.

Lo interesante es que, a pesar de su tamaño, incorpora prácticamente todo lo necesario para empezar a trabajar con ella: el propio microcontrolador, la memoria, el circuito de alimentación y el conversor USB-serie.

Por tanto, no tenemos que diseñar toda la electrónica desde cero. Podemos conectar la placa a una protoboard, añadir unos cuantos componentes y empezar a hacer pruebas.

Características principales

CaracterísticaWemos D1 mini
MicrocontroladorESP8266EX
ProcesadorTensilica L106, 32 bits
Frecuencia80 o 160 MHz
WiFi2,4 GHz, IEEE 802.11 b/g/n
Memoria Flash habitual4 MB
Entradas/salidas digitalesHasta 11, según las funciones utilizadas
Entrada analógica1, A0
Rango de A0 en la placa original habitualHasta unos 3,2 V
Nivel lógico de GPIO3,3 V
Alimentación habitual5 V por USB
Tensión de funcionamiento del chipAproximadamente 3,3 V
Dimensiones aproximadas34,2 × 25,6 mm

Estos datos corresponden a la Wemos D1 mini habitual. Si tenéis una revisión diferente o una placa compatible, conviene comprobar sus especificaciones, especialmente las relacionadas con la alimentación y la entrada analógica.

La documentación oficial de la placa se puede consultar aquí: LOLIN D1 mini.

¿Qué componentes encontramos en la placa?

Aunque no vamos a diseñar una placa desde cero, creo que merece la pena conocer qué tenemos entre manos.

  • ESP8266: es el microcontrolador encargado de ejecutar nuestro programa y gestionar la conexión WiFi.

  • Memoria Flash: almacena el firmware y otros datos del dispositivo.

  • Regulador de tensión: permite obtener los 3,3 V necesarios para el funcionamiento a partir de la alimentación USB en los modelos que lo incorporan.

  • Conversor USB-serie: permite que nuestro ordenador se comunique con el microcontrolador para cargar los programas.

  • Antena WiFi: normalmente está integrada en el propio módulo.

  • Pines GPIO: son las conexiones que utilizaremos para leer sensores y controlar componentes externos.

  • Entrada A0: nos permite medir una tensión analógica dentro del rango admitido por la placa.

Una cosa importante: aunque podamos alimentar la placa mediante USB a 5 V, eso no significa que sus entradas y salidas digitales trabajen a 5 V. Los GPIO del ESP8266 utilizan lógica de 3,3 V y no son tolerantes a 5 V.

Por tanto, mucho cuidado con conectar directamente señales de otros circuitos que trabajen a 5 V.

¿Qué consumo tiene el ESP8266?

Este es un tema interesante, sobre todo si queremos utilizar la Wemos D1 mini en un dispositivo que funcione con batería.

El consumo depende mucho de lo que esté haciendo el microcontrolador. No es lo mismo tenerlo conectado a una red WiFi transmitiendo datos que mantenerlo dormido la mayor parte del tiempo.

Como referencia, el chip puede consumir del orden de 80 mA en determinadas condiciones de funcionamiento. Durante las transmisiones WiFi aparecen picos que pueden rondar los 120–170 mA o incluso variar más según las condiciones.

Hay que tener en cuenta que estos valores corresponden al chip y a condiciones concretas. La placa completa puede consumir más debido al regulador, los LED y el resto de componentes.

¿Y qué ocurre si queremos reducir el consumo? Pues podemos utilizar los modos de ahorro energético del ESP8266, incluido el deep sleep. En este modo se desactiva la mayor parte de la actividad del sistema mientras espera el siguiente ciclo de trabajo.

Eso sí, si queremos despertar periódicamente desde deep sleep en la Wemos D1 mini, hay que tener en cuenta la conexión entre D0 (GPIO16) y RST, necesaria para el despertar temporizado en los diseños habituales.

Para un dispositivo que mida la temperatura cada varios minutos, envíe el dato por WiFi y vuelva a dormir, puede ser una solución bastante interesante. Para mantener una conexión WiFi activa de forma continua, en cambio, el consumo será considerablemente mayor.

Esquema de pines de la Wemos D1 mini

Vamos ahora con los pines, que son los que utilizaremos para conectar los diferentes componentes.

La placa utiliza nombres como D0, D1, D2 y así sucesivamente. Estos nombres corresponden a los GPIO internos del microcontrolador.


Pin de la placaGPIOUso habitual
D0GPIO16E/S digital y despertar desde deep sleep
D1GPIO5E/S digital, habitual para SCL
D2GPIO4E/S digital, habitual para SDA
D3GPIO0E/S digital; pin de arranque
D4GPIO2E/S digital; LED integrado en muchas versiones
D5GPIO14E/S digital; SPI SCLK
D6GPIO12E/S digital; SPI MISO
D7GPIO13E/S digital; SPI MOSI
D8GPIO15E/S digital; pin de arranque
RXGPIO3UART RX
TXGPIO1UART TX
A0ADCEntrada analógica
3V3—Alimentación de 3,3 V
5V—Línea de alimentación de 5 V
GND—Masa

No todos los pines están disponibles para cualquier uso en todas las circunstancias. Algunos intervienen en el arranque del microcontrolador y otros se comparten con funciones periféricas.

Para empezar, yo utilizaría D1 para el LED y A0 para el sensor analógico. De esta forma evitamos complicarnos demasiado con los pines de arranque.

¿Qué podemos hacer con la entrada analógica?

Aquí hay un detalle que conviene explicar porque puede dar algún disgusto si no lo tenemos en cuenta.

El ESP8266 incorpora un convertidor analógico-digital de 10 bits. Esto significa que podemos obtener lecturas entre 0 y 1023, que representan distintos niveles de tensión.

Sin embargo, el ADC interno del chip admite una tensión de entrada de aproximadamente 0 a 1 V.

La Wemos D1 mini habitual incorpora un divisor resistivo en su circuito de entrada A0, por lo que el terminal de la placa puede admitir aproximadamente hasta 3,2 V. Esto no es lo mismo que conectar una señal de 3,2 V directamente al ADC del chip: es la electrónica de la placa la que adapta esa tensión.

¿Y qué pasa si tenemos un sensor que entrega una señal de 0–5 V? Pues que necesitamos reducir la tensión antes de conectarlo a A0.

En el ejemplo que vamos a hacer utilizaremos un divisor resistivo externo. Aunque la Wemos D1 mini admite una tensión mayor en A0, reduciremos la señal a un máximo de 2,5 V para disponer de un margen de seguridad.

Vamos a encender un LED y leer un sensor analógico

Bueno, vamos con la parte práctica, de momento sencilla.

La idea es montar un pequeño circuito que nos permita comprobar que podemos controlar una salida digital y leer una entrada analógica con la misma placa.

Para ello vamos a necesitar:

  • Una Wemos D1 mini.

  • Un LED.

  • Una resistencia de 220–330 Ω para el LED.

  • Un sensor analógico con salida de 0–5 V.

  • Una resistencia de 10 kΩ.

  • Otra resistencia de 10 kΩ para el divisor de tensión.

  • Una protoboard y cables de conexión.

Si el sensor que vais a utilizar trabaja a 3,3 V o tiene una salida diferente, habrá que adaptar el circuito a sus características.

Conexión del LED

Conectaremos el pin D1 de la Wemos a una resistencia de 220–330 Ω y, desde ella, al ánodo del LED. El cátodo del LED irá conectado a GND.

La resistencia sirve para limitar la corriente y proteger tanto el LED como la salida del microcontrolador.

Conexión del sensor de 0–5 V

Para adaptar la señal utilizaremos dos resistencias de 10 kΩ formando un divisor de tensión.

La conexión será la siguiente:

  1. La salida analógica del sensor se conecta a una resistencia de 10 kΩ.

  2. El otro extremo de esa resistencia será nuestro punto de medida.

  3. Desde ese punto conectaremos la segunda resistencia de 10 kΩ a GND.

  4. El punto intermedio se conecta a A0 de la Wemos D1 mini.

  5. Uniremos GND del sensor con GND de la Wemos.

Con este divisor, una señal de 5 V se convierte en aproximadamente 2,5 V.

La fórmula que utilizamos es:


Si ambas resistencias tienen el mismo valor, la tensión se divide aproximadamente por dos.

OJO: comprueba que la salida del sensor puede conectarse de esta forma y que comparte una masa compatible con el circuito. No conectes los 5 V directamente a A0 ni a ningún GPIO. Si se trata de una señal industrial, una salida diferencial o un sensor con una salida especial, puede ser necesario utilizar un circuito de adaptación diferente.

Código para Arduino IDE

Vamos a programar la Wemos para que encienda el LED durante medio segundo, lo apague durante otro medio segundo y lea la tensión analógica del sensor.

const int LED_PIN = D1;
const int SENSOR_PIN = A0;

// Valores del divisor resistivo
const float R1 = 10000.0;
const float R2 = 10000.0;

// Rango nominal de A0 en la Wemos D1 mini
const float A0_MAX_VOLTAGE = 3.2;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Serial.begin(115200);
  Serial.println();
  Serial.println("Wemos D1 mini - ESP8266");
  Serial.println("Lectura de sensor analogico");
}

void loop() {
  // Encender y apagar el LED
  digitalWrite(LED_PIN, HIGH);
  delay(500);

  digitalWrite(LED_PIN, LOW);
  delay(500);

  // Leer el ADC
  int lectura = analogRead(SENSOR_PIN);

  // Estimar la tension presente en A0
  float tensionA0 =
      (lectura / 1023.0) * A0_MAX_VOLTAGE;

  // Calcular la tension original del sensor
  float tensionSensor =
      tensionA0 * (R1 + R2) / R2;

  Serial.print("Lectura ADC: ");
  Serial.print(lectura);

  Serial.print(" | Tension A0: ");
  Serial.print(tensionA0, 2);
  Serial.print(" V");

  Serial.print(" | Tension sensor: ");
  Serial.print(tensionSensor, 2);
  Serial.println(" V");
}

Este programa utiliza el rango nominal de aproximadamente 3,2 V de la entrada A0 de la Wemos D1 mini habitual. No es una calibración de precisión: las tolerancias de las resistencias, la placa y el ADC pueden producir diferencias.

Si queremos obtener medidas más precisas, podemos comparar la lectura con un multímetro y ajustar el valor de A0_MAX_VOLTAGE según el comportamiento real de nuestra placa.

Además, el código calcula la tensión del sensor, no su temperatura. Para convertir esa tensión en grados tendremos que conocer el modelo de sensor que estamos utilizando y su curva de respuesta.

¿Cómo cargamos el programa?

Primero conectaremos la Wemos D1 mini al ordenador mediante un cable USB de datos.

Después abriremos Arduino IDE y seleccionaremos la placa correspondiente. En el menú de placas, una opción habitual es LOLIN(WEMOS) D1 R2 & mini, disponible al instalar el paquete ESP8266.

Pulsamos en verificar para comprobar que el programa compila y, si todo está correcto, lo subimos a la placa.

Una vez terminado, abrimos el monitor serie y seleccionamos 115200 baudios. Deberíamos ver la lectura del ADC y la tensión calculada del sensor.

Si no aparece ningún dato, revisad el puerto serie, la velocidad configurada y que el cable USB permita transmitir datos.

¿Cómo programar el ESP8266? Te doy dos opciones

Aunque en el ejemplo anterior hemos utilizado Arduino IDE, tenemos otras posibilidades.

1. Arduino IDE

Es la opción que utilizaría para empezar a aprender a programar el microcontrolador.

Lo primero es descargar Arduino IDE desde su página oficial:

https://www.arduino.cc/en/software

Después debemos instalar el soporte para ESP8266.

En las preferencias del programa, añadiremos esta dirección al apartado de URLs adicionales del gestor de placas:

https://arduino.esp8266.com/stable/package_esp8266com_index.json

A continuación, abrimos el gestor de placas, buscamos ESP8266 e instalamos el paquete correspondiente.

Una vez instalado, seleccionamos la placa Wemos D1 mini, elegimos el puerto serie y ya podemos cargar nuestro programa. Os debería aparecer como en esta imagen que os adjunto.


Lo bueno de esta opción es que tenemos acceso a un montón de bibliotecas para trabajar con sensores, pantallas, comunicaciones WiFi, MQTT y otros componentes.

Documentación oficial: https://github.com/esp8266/Arduino

2. ESPHome




La segunda opción es ESPHome, que me parece especialmente interesante cuando nuestro objetivo es integrar el dispositivo en Home Assistant. Ojo la imagen anterior corresponde a otro de mis Scripts con un sensor de gas.

En lugar de escribir todo el programa en C++, definimos los componentes y su comportamiento mediante un archivo YAML. ESPHome se encarga de generar el firmware correspondiente.

Por ejemplo, podemos crear una configuración para la Wemos D1 mini que controle el LED y publique una lectura analógica.

esphome:
  name: sensor-wemos
  friendly_name: Sensor Wemos D1 mini

esp8266:
  board: d1_mini

wifi:
  ssid: "NOMBRE_DE_TU_WIFI"
  password: "CONTRASENA_WIFI"

logger:
  baud_rate: 0

api:

ota:
  - platform: esphome

sensor:
  - platform: adc
    pin: A0
    name: "Tension A0"
    id: tension_a0
    update_interval: 5s
    filters:
      - multiply: 3.2

switch:
  - platform: gpio
    pin: GPIO5
    name: "LED Wemos"
    id: led_wemos

En este ejemplo, ESPHome crea un sensor y un interruptor que podremos utilizar desde Home Assistant.

¿Que es eso del multiply? --->> El filtro multiply: 3.2 es una conversión orientativa para obtener la tensión aproximada en el terminal A0 a partir de una lectura normalizada de 0 a 1. Debe comprobarse con la versión de ESPHome y la placa utilizada, y no representa todavía la tensión original del sensor de 0–5 V.

Para mostrar la tensión del sensor, habrá que aplicar también la relación del divisor resistivo. En este caso, al utilizar dos resistencias iguales, la tensión original es aproximadamente el doble de la tensión presente en A0.

ESPHome dispone de documentación específica para el ADC y permite ajustar las lecturas mediante filtros:

https://esphome.io/components/sensor/adc/

La primera instalación suele hacerse por USB. Después, si hemos configurado correctamente el dispositivo, podremos realizar actualizaciones por WiFi.

ESP8266 frente a ESP32 y Raspberry Pi Pico W

Llegados a este punto, alguno se estará preguntando si merece la pena utilizar el ESP8266 teniendo alternativas más modernas.

Pues depende de lo que necesitemos. Aquí os dejo una tabla que me ha generado la IA de comparativas.

CaracterísticaESP8266ESP32 clásicoRaspberry Pi Pico W
Procesador32 bits, hasta 160 MHzDoble núcleo en el modelo clásico, hasta 240 MHzDoble núcleo, hasta 133 MHz
WiFiSíSíSí
BluetoothNoSí, según modeloNo en el Pico W original
ADC10 bitsHasta 12 bits, según modelo12 bits
GPIOMenos disponibles en muchos módulosMás opciones en muchas variantesAmplias opciones de E/S
Facilidad para proyectos IoTMuy buenaMuy buenaBuena
Uso habitualSensores y automatización sencillaProyectos más exigentesControl y experimentación

Hay que tener en cuenta que estas características corresponden a familias concretas. No todos los ESP32 tienen exactamente las mismas funciones y el soporte de periféricos depende de cada variante. Por ejemplo en mi caso he usado Weemos D1 mini, lleva montado ESP8266, pero existen diferentes variantes y versiones de la placa. 

Si vas a comprar alguna, mira las especificaciones del fabricante y lo que necesitas.

¿Por qué seguir utilizando el ESP8266?

Precio y tamaño. La Wemos D1 mini es pequeña y económica, por lo que resulta muy cómoda para montar dispositivos que después podemos instalar en una caja o integrar en un proyecto.

WiFi integrado. Si solo necesitamos conectividad WiFi, no hace falta añadir ningún módulo externo.

Compatibilidad. Tenemos soporte para Arduino IDE, bibliotecas de sensores y herramientas como ESPHome.

Suficiente para muchos proyectos. Si queremos leer una temperatura, controlar un relé compatible o enviar datos a Home Assistant, no siempre necesitamos la potencia adicional de un ESP32.

Ahora bien, si necesitamos Bluetooth, más memoria, más entradas analógicas o mayor capacidad de procesamiento, probablemente elegiría un ESP32 desde el principio.

No se trata de que un microcontrolador sea siempre mejor que otro, sino de elegir el que mejor se adapte a cada proyecto.

Integración en Home Assistant mediante ESPHome

Y aquí llegamos a una de las partes que más juego nos pueden dar si estamos metidos en el mundo de la domótica.

Con ESPHome podemos utilizar la Wemos D1 mini para crear nuestros propios sensores y actuadores y conectarlos con Home Assistant.

Por ejemplo, podemos montar un sensor de temperatura, monitorizar una señal analógica, controlar una iluminación de baja tensión o activar una salida cuando se cumpla una condición.

Una vez integrado, podremos consultar los valores desde el panel de Home Assistant y utilizarlos en nuestras automatizaciones.

¿Y cómo lo ponemos en marcha?

  1. Instalamos ESPHome y creamos un nuevo dispositivo.

  2. Seleccionamos la plataforma ESP8266 y la placa d1_mini.

  3. Configuramos la red WiFi y los componentes que queremos utilizar.

  4. Compilamos el firmware y lo cargamos por USB.

  5. Conectamos el dispositivo a la red y lo añadimos a Home Assistant mediante la integración de ESPHome.

  6. Comprobamos que aparecen las entidades correspondientes y empezamos a utilizarlas en nuestras automatizaciones.

A partir de ahí, las posibilidades dependen de lo que conectemos a la placa.

Podemos registrar la temperatura de una habitación, encender un ventilador cuando se supere un umbral o utilizar un sensor externo para activar una notificación.

Eso sí, si vamos a controlar cargas de 230 V o equipos que consumen bastante corriente, necesitaremos una etapa de potencia adecuada y las protecciones correspondientes. No debemos conectar ese tipo de cargas directamente a los pines del ESP8266.

También hay que tener presente que el ESP8266 dispone de menos recursos que el ESP32, por lo que algunas configuraciones complejas pueden requerir una plataforma más potente.

Documentación:

Conclusión

Como veis, tenemos muchas posibilidades con una placa tan pequeña como la Wemos D1 mini.

Podemos programarla desde Arduino IDE, conectar sensores, controlar salidas y comunicarnos por WiFi sin necesidad de añadir demasiados componentes externos.

Y si además la combinamos con ESPHome y Home Assistant, podemos crear nuestros propios dispositivos domóticos sin tener que desarrollar todo el sistema de comunicaciones desde cero.

Aunque el ESP32 ofrece más prestaciones, el ESP8266 sigue siendo una opción muy válida para proyectos sencillos donde no necesitamos tanta potencia.

Al final, lo interesante es aprovechar lo que tenemos y elegir el hardware adecuado para cada necesidad.

Espero que os haya resultado útil y que os animéis a probarlo. Os dejo también el link de otra de mis entradas usando el mismo Weemos D1 mini con un sensor de presión LINK.

En la siguiente entrada sobre ESP8266 os mostraré un proyecto que comencé hace tiempo de un tiesto inteligente. Combina ESP8266 con diferentes sensores y un display donde nos indica el estado del sustrato de nuestra planta. Añadiendo la guinda al pastel conectándolo a HomeAsistant.

¡Nos vemos en la siguiente entrada!


martes, 20 de octubre de 2026

¿Ensamblador?¿Obsoleto?

Programación en ensamblador de microcontroladores PIC: por qué todavía importa



En una época dominada por Arduino, ESP32 y lenguajes de alto nivel, hablar de ensamblador puede parecer hablar de arqueología informática. Y sin embargo, en el mundo de los microcontroladores (y en particular en la familia PIC de Microchip) el ensamblador sigue teniendo un papel importante. Yo reconozco que cuando lo vi en el temario de la asignatura de la Universidad... Pensé... ¿Estamos locos? Con lo maravilloso que es Python o lo fácil que puede ser programar un Arduino. xD

En esta entrada vamos a ver por qué merece la pena aprenderlo, qué son los registros de un PIC explicados de forma sencilla, y cómo se estructura un programa en ensamblador con varios ejemplos comentados línea a línea.

¿Por qué aprender ensamblador si "está obsoleto"?

Es cierto que hoy en día casi nadie desarrolla aplicaciones completas en ensamblador. Compiladores de C, C++ e incluso Python (con MicroPython) generan código lo bastante bueno para la mayoría de usos. Pero el ensamblador conserva ventajas que ningún lenguaje de alto nivel te ofrece:

  • Entiendes realmente cómo funciona el microcontrolador. Con ensamblador no hay capas de abstracción: tú mueves los datos entre registros, tú activas los bits de configuración, tú controlas cada ciclo de instrucción. Aprendes qué hace la máquina, no solo qué hace el compilador.

  • Control absoluto del tiempo de ejecución. En un PIC cada instrucción tarda 4 ciclos de reloj (1 µs a 4 MHz, salvo saltos que tardan el doble). Eso permite temporizaciones exactísimas, algo crítico en comunicaciones como RS-232 "a mano" o generación de señales.

  • Eficiencia máxima en recursos. Los PIC más pequeños (10F, 12F) tienen muy poca memoria flash y RAM. En ensamblador el programa es tan pequeño como tú lo escribas; no hay librerías ni código de arranque innecesario.

  • Es la mejor herramienta didáctica. Para quien estudia electrónica o informática industrial, el ensamblador conecta el hardware con el software: registros, interrupciones, timers, puertos… todo queda a la vista.

  • Depuración y trabajo a bajo nivel. Cuando hay que analizar o parchear código máquina, entender ensamblador es imprescindible.

En resumen: no es el lenguaje más productivo, pero es el que más te enseña y el que más control te da.

Los registros de un PIC, explicados de forma sencilla

Puedes imaginar un microcontrolador PIC como una pequeña oficina: dentro hay cajones (los registros) donde se guardan temporalmente datos e instrucciones, y unas notitas pegadas en cada cajón (los bits de configuración) que dicen qué hace cada cosa.


Un registro no es más que una memoria muy rápida, normalmente de 8 bits, que está dentro del propio chip. Cada registro tiene una dirección y una función.

En un PIC hay dos tipos de registros:

  • SFR (Special Function Registers, registros de función especial): son los "cajones oficiales" del chip, con una misión concreta asignada por el fabricante. Cada bit tiene un significado: configurar un puerto, arrancar un timer, activar una interrupción… No los eliges tú: vienen fijos de fábrica en direcciones concretas de la RAM. Los de la tabla de abajo son todos SFR.

  • GPR (General Purpose Registers, registros de propósito general): son los "cajones libres": posiciones de RAM sin función asignada que tú usas como variables del programa. Cuando en un ejemplo reservamos Contador con CBLOCK, lo que hacemos es darle nombre a un GPR. A partir de ahí, es solo un cajón donde guardas y lees datos.

Dicho de otra forma: los SFR son el panel de control del microcontrolador (tú escribes en ellos para manejar el hardware) y los GPR son tu block de notas (tú decides qué guardar en cada uno). Físicamente ambos viven en la misma RAM, solo se distinguen por su función y dirección.

Los SFR más importantes:

Registro

Nombre

¿Para qué sirve?

W

Working register

El "cajón" de trabajo. Casi todas las operaciones pasan por él. Es como la calculadora de mano del micro.

STATUS

Estado

Guarda banderas (flags) que informan del resultado de las operaciones: si hubo acarreo (C), si el resultado fue cero (Z), etc.

PORTA / PORTB

Puertos de E/S

Reflejan el estado físico de los pines: escribir en ellos pone pines a 1 o 0; leerlos te dice si hay tensión en cada pin.

TRISA / TRISB

Dirección de los pines

Configuran cada pin como entrada (1) o salida (0). "TRIS" viene de triestado.

OPTION_REG

Opciones

Configura el temporizador TMR0, el prescaler y las interrupciones por flanco en RB0.

INTCON

Control de interrupciones

Activa/desactiva interrupciones y guarda sus flags.

TMR0

Temporizador 0

Un contador que se incrementa solo y permite medir tiempos.

FSR / INDF

Puntero indirecto

Sirven para acceder a posiciones de memoria RAM "por dirección", como un puntero.

Dos ideas clave para entenderlo todo:

  1. Todo en un PIC son registros. Leer un pin, mandar un dato por el puerto serie o cambiar la velocidad de un timer se hace siempre igual: escribiendo o leyendo bits de un registro.

  2. El registro W es el protagonista. Cargar un dato en W (MOVLW), moverlo a un registro (MOVWF), sumarlo (ADDWF)… el flujo normal de un programa en ensamblador es un ir y venir de datos entre W y el resto de registros.

En la siguiente tabla se puede ver el resumen de los registros de función especial(SFR) del PIC16F84A(extraído del datasheet)



Las directivas principales del ensamblador (MPASM)

Las directivas no son instrucciones del PIC: son órdenes que se le dan al ensamblador (MPASM, el de Microchip) para que prepare el código. Las más usadas:

  • LIST P=16F84A — Indica el modelo de PIC para el que se ensambla.

  • #INCLUDE <P16F84A.INC> — Incluye el fichero de Microchip con los nombres de todos los registros y bits, para no tener que memorizar direcciones.

  • __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF — Graba los fusibles de configuración: tipo de oscilador, watchdog desconectado, etc.

  • ORG 0x00 — Indica en qué dirección de memoria empieza el código (0x00 es el vector de reset; 0x04, el de interrupción).

  • EQU — Define constantes con nombre (por ejemplo, para dar nombre a una variable).

  • CBLOCK ... ENDC — Reserva posiciones de RAM para variables.

  • END — Marca el fin del código fuente.

Además, conviene recordar los modos de direccionamiento de las instrucciones, porque en los ejemplos aparecen constantemente:

  • W → el destino es el registro W (ej.: ADDWF REG, W guarda el resultado en W).

  • F → el destino es el propio registro (ej.: MOVWF PORTB).

  • LW → "literal en W": el dato viaja directamente (ej.: MOVLW 0xFF).

  • Etiquetas → direcciones de salto (ej.: GOTO Bucle).


En la siguiente imagen se puede ver un ejemplo de una práctica que tuve que realizar empleando MPLAB X(uso V5.35 por estabilidad en mi pc)



Las instrucciones más comunes del ensamblador PIC

Un PIC16F solo entiende 35 instrucciones, pero con menos de 20 se escribe el 90 % de los programas. Estas son las que usarás a diario, agrupadas por lo que hacen:

Mover datos:

  • MOVLW → MOVe Literal to W. Carga una constante en W. Ej.: MOVLW d'255'.

  • MOVWF → MOVe W to File. Copia W a un registro. Ej.: MOVWF PORTB.

  • MOVF → MOVe File. Copia un registro a W (MOVF Contador, W) o a sí mismo. Es la forma de leer variables.

  • SWAPF → SWAP File. Intercambia los dos nibbles (4 bits) de un registro. Su uso estrella es restaurar W sin tocar las banderas.

Aritmética y lógica:

  • ADDWF → ADD W to File. Suma W a un registro.

  • SUBLW → SUBtract W from Literal. Resta W de una constante (guardando el resultado en W).

  • ANDWF / IORWF / XORWF → Operaciones lógicas AND, OR y XOR entre W y un registro. Imprescindibles para poner, borrar o invertir bits concretos.

  • INCF / DECF → INCrement / DECrement File. Suman o restan 1 a un registro.

  • COMF → COMplement File. Invierte todos los bits de un registro.

  • RLF / RRF → Rotate Left/Right through Carry. Rotan los bits a izquierda o derecha pasando por la bandera C (multiplicar/dividir por 2, registros de desplazamiento).

Manipular bits:

  • BSF → Bit Set File. Pone a 1 un bit de un registro. Ej.: BSF PORTB, 0.

  • BCF → Bit Clear File. Pone a 0 un bit. Ej.: BCF STATUS, RP0.

  • BTFSC → Bit Test File, Skip if Clear. Si el bit vale 0, salta la instrucción siguiente (equivale a "si… entonces").

  • BTFSS → Bit Test File, Skip if Set. Lo mismo pero al revés: salta si el bit vale 1.

Saltos y control del programa:

  • GOTO → GO TO. Salto incondicional a una etiqueta. Con él se construyen los bucles.

  • CALL / RETURN → Llaman a una subrutina y vuelven de ella.

  • RETFIE → RETurn From Interrupt and Enable. Vuelve de una interrupción reactivándolas.

  • DECFSZ → DECrement File, Skip if Zero. Resta 1 y salta la siguiente instrucción si el resultado es cero. Es LA instrucción de los bucles de repetición y los retardos.

  • INCFSZ → Igual que la anterior pero sumando 1.

  • CLRW / CLRF → Ponen a 0 el registro W o un registro completo (ej.: CLRF TRISB).

  • NOP → No OPeration. No hace nada; sirve para perder un ciclo, como hueco o para temporizaciones finas.

Truco para recordarlas: el nombre casi siempre es la contracción de su significado en inglés (BSF = Bit Set File, DECFSZ = DECrement File Skip if Zero). Cuando interiorices esa lógica, el instruction set se lee solo.


_________________________________________________________________________________

Unos ejemplillos comentados línea a línea

Todos los ejemplos son para el PIC16F84A, un clásico de aprendizaje. Fíjate en cómo cada instrucción hace una sola cosa muy simple: la potencia viene de combinarlas.

Ejemplo 1: Hola mundo — encender un LED

    LIST    P=16F84A            ; Indicamos el modelo de PIC
    #INCLUDE <P16F84A.INC>      ; Nombres de registros y bits
    __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
                                ; Oscilador a cristal, watchdog OFF

    ORG     0x00                ; El programa empieza en la dirección 0
    BSF     STATUS, RP0         ; Paso al banco 1 de memoria (RP0=1)
    MOVLW   b'11111110'         ; Cargo en W el valor 11111110 (RB0 salida)
    MOVWF   TRISB               ; Lo copio a TRISB: RB0 salida, resto entradas
    BCF     STATUS, RP0         ; Vuelvo al banco 0 (donde está PORTB)
    BSF     PORTB, 0            ; Pongo RB0 a "1": el LED se enciende
Bucle:
    GOTO    Bucle               ; Bucle infinito: no hacemos nada más

    END                         ; Fin del código fuente

Qué hace: configura RB0 como salida y lo pone a 1, dejando el LED encendido para siempre. Nótese que b'11111110' es binario: el bit 0 vale 0, y en TRIS un 0 significa salida.

Ejemplo 2: Parpadeo de un LED

    LIST    P=16F84A
    #INCLUDE <P16F84A.INC>
    __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    ORG     0x00
    BSF     STATUS, RP0         ; Banco 1
    MOVLW   b'11111110'         ; RB0 como salida
    MOVWF   TRISB
    BCF     STATUS, RP0         ; Banco 0
Parpadeo:
    BSF     PORTB, 0            ; LED ON
    CALL    Retardo             ; Espero un tiempo (subrutina)
    BCF     PORTB, 0            ; LED OFF
    CALL    Retardo             ; Espero otro rato
    GOTO    Parpadeo            ; Repito eternamente

Retardo:                        ; --- Subrutina de retardo ---
    MOVLW   d'255'              ; W = 255 (d'255' = 255 en decimal)
    MOVWF   0x0C                ; Lo guardo en una posición de RAM (contador)
Decremento:
    DECFSZ  0x0C, F            ; Resto 1 al contador; si da 0, salto la
                                ; siguiente instrucción (SZ = skip if zero)
    GOTO    Decremento         ; Todavía no es cero: sigo restando
    RETURN                      ; Contador a cero: vuelvo al programa principal

    END

¿Qué hace este programilla? el LED parpadea. El truco del retardo es DECFSZ: resta 1 bit y salta la instrucción siguiente si el resultado es cero. Es una de las instrucciones más usadas del PIC.

Ejemplo 3: Leer un botón y actuar sobre un LED

    LIST    P=16F84A
    #INCLUDE <P16F84A.INC>
    __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    ORG     0x00
    BSF     STATUS, RP0         ; Banco 1
    MOVLW   b'11111110'         ; RB0 salida (LED)...
    MOVWF   TRISB              ; ...y RB1..RB7 de entrada (ahí irá el botón)
    MOVLW   b'00010000'         ; RA4 como entrada (ahí conecto el botón)
    MOVWF   TRISA
    BCF     STATUS, RP0         ; Banco 0
Espera:
    BTFSC   PORTA, 4            ; "Bit Test File, Skip if Clear":
                                ; si RA4 es 0 (botón pulsado),
                                ; salto la siguiente instrucción
    GOTO    Espera              ; RA4 sigue a 1 (botón sin pulsar): sigo esperando
    BSF     PORTB, 0            ; Botón pulsado: enciendo el LED
Suelta:
    BTFSS   PORTA, 4            ; "Skip if Set": si RA4 vuelve a 1
                                ; (botón soltado), salto la siguiente
    GOTO    Suelta               ; Sigue pulsado: espero
    BCF     PORTB, 0            ; Botón soltado: apago el LED
    GOTO    Espera              ; Vuelvo a esperar otra pulsación

    END

¿Qué hace este nuevo programa?: espera a que pulses el botón conectado a RA4 para encender el LED, y lo apaga al soltarlo. BTFSC y BTFSS son las dos instrucciones de test de bits, las "responsables" de casi toda la toma de decisiones en ensamblador.

Ejemplo 4: Contador en el puerto B (8 LEDs en binario)

    LIST    P=16F84A
    #INCLUDE <P16F84A.INC>
    __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    CBLOCK  0x0C                ; A partir de la dirección 0x0C de RAM...
    Contador                   ; ...reservo una variable llamada "Contador"
    GuardaRet                  ; ...y otra para guardar contadores de retardo
    ENDC

    ORG     0x00
    BSF     STATUS, RP0         ; Banco 1
    CLRF    TRISB               ; TRISB = 0: todo el puerto B como salida
    BCF     STATUS, RP0         ; Banco 0
    CLRF    Contador            ; Contador = 0
Bucle:
    MOVF    Contador, W         ; Copio Contador a W (MOVF mueve de registro a W)
    MOVWF   PORTB              ; Lo saco por el puerto B: 8 LEDs muestran
                                ; el valor en binario
    INCF    Contador, F        ; Contador = Contador + 1 (INCrement File)
    CALL    Retardo             ; Espero un poco para que se vea
    GOTO    Bucle               ; Siguiente valor

Retardo:
    MOVLW   d'50'               ; Bucle doble para alargar la espera
    MOVWF   GuardaRet
Bucle1:
    MOVLW   d'255'
    MOVWF   Contador            ; Reutilizo Contador como variable interna
Bucle2:
    DECFSZ  Contador, F        ; Bucle interno (255 vueltas)
    GOTO    Bucle2
    DECFSZ  GuardaRet, F       ; Bucle externo (50 vueltas)
    GOTO    Bucle1
    RETURN

    END

Poco a poco lo vamos complicando, ¿Que hace ahora nuestro código?: cuenta de 0 a 255 sin parar mostrando cada valor en binario sobre 8 LEDs conectados al puerto B. Fíjate en MOLF… perdón, en MOVF: mientras MOVLW carga una constante en W, MOVF copia el contenido de un registro (¡importante para leer variables!).

Ejemplo 5: Interrupción por cambio en RB0

    LIST    P=16F84A
    #INCLUDE <P16F84A.INC>
    __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    CBLOCK  0x0C
    GuardaW                    ; Aquí guardaré W al entrar en la interrupción
    GuardaSTATUS               ; ...y aquí STATUS (¡imprescindible!)
    ENDC

    ORG     0x00                ; Vector de RESET: por aquí se empieza
    GOTO    Inicio              ; Salto sobre el vector de interrupción
    ORG     0x04                ; Vector de INTERRUPCIÓN: la CPU salta aquí
                                ; automáticamente cuando ocurre
    MOVWF   GuardaW             ; Salvo W (la interrupción puede llegar
                                ; en cualquier momento del programa)
    MOVF    STATUS, W           ; Copio STATUS a W...
    MOVWF   GuardaSTATUS        ; ...y lo salvo también
    BCF     INTCON, INTF        ; Borro el flag que avisó de la interrupción
                                ; (si no, saltaría eternamente)
    BTFSC   PORTB, 0            ; ¿RB0 está a 0?
    GOTO    Fin                 ; No: no hago nada
    BSF     PORTB, 7            ; Sí: enciendo el LED de RB7
Fin:
    MOVF    GuardaSTATUS, W     ; Restauro STATUS...
    MOVWF   STATUS
    SWAPF   GuardaW, F          ; SWAPF intercambia nibbles sin tocar las
    SWAPF   GuardaW, W          ; banderas: truco clásico para restaurar W
    RETFIE                     ; Retorno de interrupción (RETurn From
                                ; Interrupt and Enable)
Inicio:
    BSF     STATUS, RP0         ; --- Configuración ---
    MOVLW   b'00000001'         ; RB0 entrada, resto del puerto B salida
    MOVWF   TRISB
    BCF     OPTION_REG, INTEDG  ; Interrupción en flanco de bajada de RB0
    BCF     STATUS, RP0
    BSF     INTCON, INTE        ; Activo la interrupción de RB0
    BSF     INTCON, GIE         ; Activo las interrupciones en general
Bucle:
    GOTO    Bucle               ; El programa "duerme": todo lo hace la ISR

    END

Nuestro último programilla... el programa principal no hace nada; cuando el pin RB0 detecta un flanco de bajada (por ejemplo, un botón con lógica negativa), la CPU salta sola a la dirección 0x04, se ejecuta la rutina de interrupción y luego RETFIE devuelve el control. Observa el ritual de guardar W y STATUS al entrar y restaurarlos al salir: sin eso, la interrupción "corrompería" el programa principal. El truco de SWAPF dos veces se usa porque SWAPF no afecta a las banderas del registro STATUS.

Conclusiones

El ensamblador en los PIC no ha muerto: ha cambiado de papel. Ya no es la forma habitual de desarrollar productos, pero sigue siendo la mejor escuela posible para entender qué pasa de verdad dentro de un microcontrolador: registros, bancos de memoria, temporizaciones exactas e interrupciones sin capas de por medio. Si algún día programas en C un PIC (o cualquier otro micro), verás que lo que hace el compilador por debajo ya no será magia para ti… porque habrás escrito eso mismo a mano.

Tengo más códigos y ejemplos que puedo compartir, si necesitas mas ayuda no dudes en escribirme. Obviamente esto son ejemplos básicos, una vez que empezamos a utilizar bucles, interrupciones o "funciones" elaborar el código de control puede complicarse bastante.

 He utilizado MPLAB X para crear los códigos y compilar, si necesitas ayuda para utilizarlo no dudes en escribirme también.

¡Espero que te sirva! ¡Un saludo!

lunes, 19 de octubre de 2026

Control de ventilación en un CPD con PIC16F876: el proyecto completo

Control de ventilación en un CPD con PIC16F876: el proyecto completo


Este es un proyecto que hice en la Universidad en una de las asignaturas. La verdad que me pareció muy interesante, pues combinada múltiples partes. Planificación de funcionamiento, diseño, programación y simulación.
He decidido compartir todo mi desarrollo para poder echar un cable a electrónicos que lo necesiten, así que aquí os lo dejo.
En la primera parte comenzaremos con el enunciado del programa y posteriormente el desarrollo del proyecto.

El contexto: por qué un CPD necesita "aire a medida"

Un CPD (Centro de Proceso de Datos) es básicamente una sala llena de RACKs de servidores trabajando sin parar, y donde hay procesadores trabajando… hay calor. Mucho calor. Para mantenerlo a rayo se usan los CRAC (Computer Room Air Conditioner), unidades de aire acondicionado específicas para salas de servidores, que crean los clásicos pasillos fríos (por donde entra el aire que respiran los servidores) y pasillos calientes (por donde expulsan el aire calentado).


El proyecto parte de un problema real: los CRAC por sí solos no siempre consiguen llevar el aire frío hasta el final de los pasillos. La solución propuesta es añadir ventilación adicional dirigida mediante la incorporación de 2 CRAC, y aquí viene lo interesante: un ventilador bajo cada pasillo frío, instalado en el suelo técnico, que empuja el aire frío justo donde hace falta.



La lógica de control: la gráfica Temperatura / Velocidad

El ventilador no gira a una velocidad fija: su potencia se ajusta según la temperatura de los pasillos calientes adyacentes, de modo que su comportamiento se ajusta a la gráfica. Cada pasillo frío tiene dos pasillos calientes adyacentes, y cada pasillo caliente dispone de 2 sondas de temperatura. La temperatura a compensar se considera la media aritmética de las 4 medidas.

Esa media se traduce en velocidad de giro siguiendo una curva Temperatura/Velocidad (T/V):




El cerebro: un microcontrolador, no un PC

Para gobernar cada ventilador se propone un microcontrolador (un chip programable de toda la vida, sin sistema operativo ni nada parecido) capaz de capturar el valor de dichas temperaturas y generar una señal PWM que controle la velocidad de giro de su motor de corriente continua, siguiendo la curva T/V antes mencionada.

Requisitos funcionales del proyecto 

Aquí va la lista oficial de requisitos, que es donde está la "chicha" técnica:

  1. Microcontrolador: se usará un PIC16F876 con cristal de 12 MHz.
  2. Alimentación: la tensión de alimentación del microcontrolador estará en el intervalo [4,5 V – 5,5 V].
  3. Sondas de temperatura: cada sonda entrega una tensión de salida en el intervalo [0 V, 4 V], directamente proporcional a la temperatura ambiente en [0 °C, 100 °C].
  4. Salida PWM: una vez calculada la media de las 4 temperaturas, se generará una señal PWM cuyo ciclo de trabajo (respecto al período de la señal) es igual al % de potencia obtenido en base a la curva T/V.
  5. Referencia del conversor AD: la tensión de referencia Vref = 4 V se consigue de la tensión de alimentación gracias a un circuito de adaptación. La tensión de referencia negativa será GND.
  6. Muestreo: las 4 señales analógicas de las sondas han de muestrearse cada 100 períodos PWM. Tanto la lectura de los canales analógicos como la cuenta del tiempo de muestreo se implementarán obligatoriamente mediante interrupciones.
  7. Generación PWM: la señal PWM la proporciona el PIC mediante uno de los módulos CCP en modo PWM. La frecuencia de la señal será, en kHz, el resultado de sumar 1 al último número de tu DNI (o documento equivalente), siempre que se garantice una resolución mínima de 10 bits en la señal PWM.


El "kit de parámetros" de un vistazo


Parámetro Valor
Microcontrolador  PIC16F876
Cristal 12 MHz
Alimentación 4,5 – 5,5 V
Salida de sondas                     0 – 4 V (proporcional a 0 – 100 °C)
Vref (AD) 4 V (Vref− = GND)
Muestreo Cada 100 períodos PWM (obligatoriamente por interrupciones)
PWM Módulo CCP en modo PWM, resolución mínima 10 bits
Frecuencia PWM (última cifra del DNI + 1) kHz
Curva T/V 10% hasta 20 °C · 30% a 40 °C · 60% a 60 °C · 100% a partir de 80 °C

¿Por qué estos requisitos son tan interesantes?

Cada requisito esconde una decisión de diseño digna de análisis. El Vref de 4 V es una joya: coincide exactamente con el máximo de las sondas (0–4 V), de modo que el conversor A/D aprovecha todo su rango: 0 V → 0 °C y 4 V → 100 °C, sin desperdiciar ni un bit. El muestreo cada 100 períodos PWM obliga a "casar" dos tiempos de reloj distintos (y por eso exigen interrupciones, nada de bucles de espera improvisados). Y la condición de los 10 bits de resolución limita las frecuencias PWM elegibles: no vale cualquier kHz de tu DNI, solo los que el datasheet del PIC permita con esa resolución a 12 MHz.



___________________________________________________________________________________



¿Cómo lo haremos?

Obviamente solo me pidieron el desarrollo del proyecto "sobre papel", cómo se podría implementar,  cálculos e ideas de mejora. 
Yo le quise dar un extra, así que hice los esquemáticos en Proteus, y simulación del código del programa. Así como las comprobaciones con el osciloscopio virtual del simulador.

Así que dividí el proyecto en las siguientes fases:
  1. Resumen y especificaciones solicitadas, así como soluciones y componentes a utilizar. Incluyendo cálculos.
  2. El diagrama de funcionamiento del sistema para implementar en el PIC.
  3. Cálculos previos a la programación (Fosc, TMR1, TMR2, TPWM) y cálculos adicionales para el funcionamiento.
  4. Simulación en Proteus
  5. Conclusiones finales.


1.      Resumen de especificaciones solicitadas y consideraciones previas

a.       Resumen de especificaciones y requisitos para tener en cuenta

 

·        Microcontrolador-> PIC16F876 con frecuencia de cristal 12MHz

·        Tensión de alimentación del micro [4.5,5.5V]

·        Sonda de temperatura debe proporcionar una señal de salida [0,4V], proporcional a [0ºC,100ºC].

·        Se calcula media de 4 sondas de temperatura, y se generará salida PWM en función de la curva T/V para controlar los ventiladores.

·        Frecuencia de PWM de 1KHz, según la condición impuesta.

 

b.      ¿Qué elementos y componentes electrónicos usar?

 

Microcontrolador:

El microcontrolador a emplear será el PIC16F876, este es un microcontrolador de 8 bits de la familia de Microchip Technology, con un encapsulado de 28 pines.

Cuenta con arquitectura RISC y memoria Flash reprogramable. Ofrece módulos periféricos integrados como ADC, PWM, Timers (TMR0,TMR1 y TMR2), y comunicación serial (UART, SPI, I2C).

Es ampliamente utilizado en aplicaciones embebidas de tamaño medio debido a su versatilidad, bajo costo y facilidad de uso con compiladores. En este caso utilizaremos el software MPLAB X IDE 5.35 y el compilador XC8 para la creación del algoritmo y simulación.

Además, como punto extra, he realizado un esquemático en PROTEUS 8.5 para realizar una simulación adicional más real que la que podemos hacer con MPLAB 


Sensores de temperatura:

En el enunciado de la práctica se indica que debemos utilizar 4 sensores de temperatura para la monitorización de temperatura, sin dar más detalles.

Existen infinidad de sensores que se podrían implementar, pero en mi caso en varios proyectos personales he utilizado el clásico sensor de temperatura LM35, así que esa fue mi elección.

Información de este sensor:

El sensor de temperatura LM35 es ligero, fiable, compacto y sencillo de utilizar.

·        Encapsulado To92, con 3 pines Vcc(+5Vdc), GND y Vout.

·        Vout, nos proporciona una salida de tensión analógica, lineal con una pendiente de 10mV/ºC.

·        Rango de tensión de salida desde 0 Voltios(0ºC) a 1.5 Voltios(150ºC).

·        Rango de medida de -55ºC a 150ºC.

·        Bajo consumo: inferior a 60uA

·        Alta precisión, ±0.5°C a 25°C.

 


Circuito de adaptación:

Como requisito, se pide que los sensores de temperatura nos proporcionen una salida de 0-4 voltios. Como el LM35 nos proporciona una tensión de salida de 0 a 1.5 voltios, es necesario hacer un circuito de adaptación de niveles.

Mi idea, sería utilizar el amplificador Operacional MCP6001 configurándolo como amplificador no inversor.

Realizando unos sencillos cálculos obtengo la ganancia que necesito y posteriormente los valores óptimos de las resistencias para dicha configuración.

 



En las siguientes imágenes se puede ver un ejemplo de la simulación en la adaptación de niveles.

   



La primera imagen, muestra como inyecto una tensión de 0Voltios obteniendo a la salida del Operacional 0 voltios.

En la segunda imagen, se establece la tensión máxima de salida del sensor (1Voltio para 100ºC) y obtenemos una señal de salida de 4 voltios que conectaremos a nuestra entrada analógica del PIC.

 

Mi idea del Esquemático electrónico del sistema:

 


2.       Diagrama de funcionamiento del sistema de refrigeración en el Micro

 



3.       Cálculos realizados previos a la programación

a.       Tiempos y periodos a calcular

Frecuencia Oscilación = 12MHz




b.      Tiempos y configuración de PWM.

Frecuencia PWM = 1KHz (Según la condición especificada)

 


 

Necesitamos comprobar que la frecuencia de la señal PWM garantiza una resolución mínima de 10bits en la misma.

Tiempo para 10bits-> 1024 pasos-> 1024 x 0,333 us = 341,33 us

Se cumple 341,33us < 1000us(1ms)

 

Es posible garantizar una resolución mínima de 10bits para una señal PWM de 1KHz y un XT de 12MHz.

                                                                             i.        Configuración TMR2          

El registro CCP1 para la generación de PWM, utiliza TMR2 para su temporización, por tanto, necesitaremos calcular el valor de PR2 en función de los requisitos establecidos.




c.       Temporización o muestreo

Según especificación, las 4 sondas de temperatura serán muestreadas cada 100 periodos PWM, así que necesitaremos un modo de temporización, para ello utilizaremos TMR1.

Como bien sabemos TMR1 en el PIC16F876 tiene una resolución de 16 bits, y visto que necesitamos una temporización elevada(100ms) necesitamos emplear un preescaler de 8.



d.      Cálculos adicionales para el funcionamiento del algoritmo

Bien, en este momento, tenemos calculado y configurado: el tiempo de muestreo o temporización, PWM&TMR2, configurado ADC.

Podríamos “tener preparado” la mayoría de los cálculos para hacer la lectura de los voltios convertidos a bits que nos arrojan los sensores. Pero necesitamos hacer una conversión de esos bits a una magnitud física que entendamos.

Se nos ha facilitado la siguiente gráfica de conversión de temperatura medida vs % de potencia de control para el ventilador.

 

Por tanto, para adaptar el modo de control a nuestro código PRIMERO he optado por realizar 2 tablas de conversión.

Tabla 1:

Conversión grados-> Escala de resolución ADC(10bits)

Grados ºC

Resolución(10bits)

0

0

10

102

20

205

30

307

40

410

50

512

60

615

70

719

80

819

90

921

100

1024

 

Con esta tabla estoy haciendo una equivalencia del rango de temperatura(0-100ºC) con el equivalente a la resolución de 10bits. Además, sabemos que el sensor LM35 nos da una salida analógica de 10mv/ºC.

 

Tabla 2:

 Registro una comparación y equivalencia de grados-> % Pot. Ventilador

Así me iré aproximando a los valores que necesitaré para escribir el DuttyC.

 

Grados ºC

%

Valor bits

0

20

205

10

23

235

20

27

265

30

30

307

40

34

350

50

44

450

60

56

575

70

72

737

80

100

1023

>80

100

1023

  

Visto que tenemos una gráfica exponencial y debido a la complejidad de insertar todos los puntos de la gráfica, opté por lo siguiente.

·        En primer lugar, pensé en dividir la temperatura en tramos y aplicar una potencia fija al ventilador para todo ese rango. No sería correcto, ya que, si la temperatura esta en el límite superior del tramo y aplicamos una potencia al ventilador inferior a la necesitada, se produciría un sobrecalentamiento y funcionamiento ineficiente. De igual manera, si la temperatura está en el límite inferior y aplicamos una potencia de ventilador máxima para ese rango, tendríamos un consumo en exceso de energía.

·        Solución aplicada.

o   He dividido la temperatura en segmentos, apoyándome en la tabla 1.

§  1º Tramo Temperatura-> Para 0≤x≤20ºC

§  2º Tramo Temperatura-> Para 20≤x≤39ºC

§  3º Tramo Temperatura-> Para 39≤x≤53ºC

§  4º Tramo Temperatura-> Para 53≤x≤66ºC

§  5º Tramo Temperatura-> Para 66≤x≤72ºC

§  6º Tramo Temperatura-> Para 72≤x≤80ºC

§  7º Tramo Temperatura-> Para >80ºC

 

o   Para obtener la potencia del ventilador, he realizado una función para cada intervalo mediante aproximación por segmentos lineales. Apoyándome en la tabla 2 y los cálculos adicionales.

Tramo 1 Temperatura(20 a 25ºC) 





4.      Funciones adicionales al programa

Terminado y comprobado el funcionamiento del programa, pensé en posibles implementaciones adicionales.

o   Registro de Alarmas e indicación visual del funcionamiento del sistema. Dependiendo de la temperatura leída, activaremos unas determinadas salidas del puerto B.

o   Usamos la salida RB0 para una indicación visual (led verde), del funcionamiento Óptimo del sistema.

o   La salida RB1, nos dará una salida óptima adicional, mediante un LED Rojo. Nos Indicará un Warning de temperatura elevada.

o   RB2, actuará también como salida y mediante un Buzzer transistorizado, nos dará un aviso acústico, indicando TEMPERATURA MUY ELEVADA.

 

o   Comprobación de funcionamiento de las sondas parejas, realizando una comparación entre su medida. Si existe una disparidad elevada entre ellas, nos dará una alarma adicional de posible fallo de sonda, activando señal óptica+ acústica. (sin terminar de implementar)


5.      Simulación en Proteus


Además de realizar las simulaciones del programa en MPLAB X, pensé usar Proteus para probar su funcionamiento, cargando el *.hex en el PIC virtual.

Nota: En estas simulaciones, apliqué una VREF de 1Voltio en vez de 4V. Motivo… mi versión del software al intentar simular con los operacionales me daba errores, así que opté por hacer la simulación con los elementos justos.

 

Midiendo una temperatura de 20 grados en los 4 sensores.



Se puede ver la salida PWM en CCP1 capturada por el analizador lógico, con un porcentaje de dutty en torno al 20%.

Medida de una temperatura de 75 grados en los 4 sensores.



Se puede ver la diferencia en la salida PWM en CCP1 respecto a la prueba en el primer rango de temperaturas.

 

Conclusiones:

Según las pruebas aplicadas en el funcionamiento, no he encontrado fallos en el funcionamiento. Si he tenido fallos al simular en MPLAB X y Proteus en varias ocasiones. Entiendo que la gestión de las interrupciones sobre la capa de Windows y el propio software no sean las condiciones más favorables.

Quedaría pendiente implementar más funciones adicionales al sistema para tener un sistema más completo, como la comprobación de sondas de temperaturas defectuosas que mencioné anteriormente.

Incluso un sensor de corriente que leyera la corriente consumida por el ventilador y si detectara un consumo bajo de corriente, el PIC leyera una señal de entrada digital o analógica (del sensor) para registrar y enviar un aviso de la avería de ventilador.

 

 *Bueno como siempre me despido de esta entrada y espero que os haya servido de ayuda. En caso de algún error o ideas de mejora siempre son recibidas para podernos ayudar entre todos.

En caso de necesitar el código o el HEX, me podéis escribir sin problema.