| | | | | |

Controlar la velocidad de ventiladores PWM de 12 V con ESPHome, ESP32 y Home Assistant

Introducción

En muchos racks domésticos, armarios técnicos o pequeños homelabs, la ventilación suele resolverse conectando varios ventiladores de PC directamente a 12 V. El problema es que, funcionando siempre al máximo, pueden generar más ruido del necesario. La alternativa es aprovechar ventiladores PWM de 4 pines, como los de una caja de PC, para regular su velocidad desde Home Assistant mediante un ESP32 y ESPHome.

En este montaje se controlan varios ventiladores de 12 V con un único ESP32. Los ventiladores reciben alimentación fija de 12 V y la velocidad se regula mediante la señal PWM del cuarto cable. Este enfoque es el adecuado para ventiladores PWM, ya que el control de velocidad no debe hacerse cortando o modulando la línea de alimentación, sino usando el pin PWM dedicado. Noctua, en su guía para microcontroladores, explica que el PWM controla la velocidad sin modificar la alimentación del ventilador y advierte expresamente de que no se debe aplicar PWM sobre la línea de alimentación, porque puede dañar el ventilador.

Objetivo del montaje

El objetivo es conseguir:

  • Controlar la velocidad de tres ventiladores PWM de 12 V.
  • Exponerlos en Home Assistant como una entidad fan.
  • Regularlos manualmente desde Home Assistant.
  • Automatizar la velocidad según la temperatura del rack.
  • Mantener alimentación independiente para motores y electrónica.
  • Evitar que los ventiladores se paren completamente, usando su velocidad mínima real como ventilación base.

En el caso práctico documentado, los ventiladores se comportan aproximadamente así:

Valor en Home AssistantVelocidad real aproximada
0 % / apagado lógico360 rpm
50 %860 rpm
100 %1500 rpm

Esto es importante, porque aunque Home Assistant muestre el ventilador como apagado, físicamente los ventiladores siguen girando a baja velocidad.

Material necesario

Para este montaje se ha usado:

  • 1 ESP32.
  • 3 ventiladores PWM de 12 V y 4 pines.
  • 1 fuente de 12 V para los motores.
  • 1 fuente de 5 V para el ESP32, o un buck de 12 V a 5 V.
  • Cableado adecuado para alimentación.
  • Resistencias de 1 kΩ a 4,7 kΩ para la señal PWM.
  • Opcional: cable para leer RPM de un único ventilador.

El ESP32 resulta especialmente adecuado para esta tarea porque ESPHome dispone del componente ledc, que expone un canal PWM hardware del ESP32 como una salida configurable. La documentación oficial indica que ledc permite seleccionar pin, frecuencia y canal, y que el rango de frecuencia del LEDC va de 10 Hz a 40 MHz.

Pinout típico de un ventilador PWM de PC

En un ventilador PWM de 4 pines, lo habitual es encontrar:

CableFunción
NegroGND
Amarillo+12 V
VerdeTACH / RPM
AzulPWM

La guía de Noctua identifica estos cuatro cables como masa, alimentación, señal RPM y señal PWM, respectivamente. También indica que la frecuencia objetivo para la señal PWM es de 25 kHz, con un rango soportado de 21 a 28 kHz, y que una frecuencia fuera de ese rango puede provocar comportamientos imprevisibles.

Esquema eléctrico

La alimentación de los ventiladores debe ir directamente desde la fuente de 12 V:

Fuente 12 V +  ───────────── +12 V ventiladores
Fuente 12 V GND ──────────── GND ventiladores

El ESP32 solo envía la señal de control PWM:

ESP32 GPIO25 ── resistencia 1k/4.7k ── PWM azul ventiladores
ESP32 GND ─────────────────────────── GND común

La masa común es imprescindible. Si el ventilador usa una fuente externa, la masa de esa fuente debe estar unida a la masa del microcontrolador para que exista una referencia común de señal. Noctua lo indica expresamente en su guía: cuando se usa una fuente externa, debe conectarse el GND del ventilador al GND del dispositivo controlador para que el PWM funcione correctamente.

El esquema general quedaría así:

FUENTE 12 V+12 V  ─────────────── +12 V motor ventilador 1
+12 V  ─────────────── +12 V motor ventilador 2
+12 V  ─────────────── +12 V motor ventilador 3
GND    ─────────────── GND motor ventilador 1/2/3

ESP32
GPIO25 ── 1k/4.7k ─── PWM ventilador 1/2/3
GND    ─────────────── GND común

No se deben unir las señales TACH/RPM de los tres ventiladores. Si se quiere medir RPM, lo recomendable es leer la señal TACH de un solo ventilador.

Si la conexión no es estandar, el sistema de conexión de ventiladores con 4 hilos es el de la siguiente imagen:

Consideraciones sobre alimentación

Durante las pruebas se detectó que una fuente supuestamente suficiente no mantenía tensión bajo carga y los ventiladores se quedaban a unas 400 rpm. Con una fuente de laboratorio a 12 V, los mismos ventiladores alcanzaban 1500 rpm consumiendo aproximadamente 0,15 A. La conclusión fue que el problema no estaba en ESPHome ni en el PWM, sino en la fuente o el cableado de alimentación.

Para tres ventiladores de este tipo, si el consumo real ronda 0,15 A, una fuente de 12 V y 1 A ya podría ser suficiente. Aun así, es recomendable usar margen:

Mínimo razonable: 12 V 1 A
Recomendado:     12 V 2 A
Sobrado:         12 V 3 A

Más importante que la cifra de amperios es que la fuente mantenga 12 V reales bajo carga.

Configuración ESPHome

El componente output de ESPHome permite crear salidas binarias o salidas flotantes; las salidas flotantes, como PWM, pueden entregar valores entre 0 y 1. Además, admite opciones como min_power, max_power, inverted y zero_means_zero.

Sobre esa salida PWM se crea una entidad fan usando la plataforma speed. La documentación de ESPHome indica que speed fan permite representar cualquier salida flotante como un ventilador con control de velocidad y que speed_count: 100 permite trabajar en incrementos del 1 %.

Ejemplo de configuración:

substitutions:
  device_name: "control-ventiladores-rack"
  friendly_name: "Control Ventiladores Rack"

esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}

esp32:
  board: esp32dev
  framework:
    type: esp-idf

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "${friendly_name} Fallback"
    password: "cambia-esta-clave"

captive_portal:

logger:

api:

ota:
  - platform: esphome

output:
  - platform: ledc
    id: fan_pwm_output
    pin: GPIO25
    frequency: 25000 Hz
    channel: 0
    min_power: 20%
    zero_means_zero: true

fan:
  - platform: speed
    id: fan_rack
    name: "Velocidad ventiladores"
    output: fan_pwm_output
    speed_count: 100
    restore_mode: RESTORE_DEFAULT_ON

sensor:
  - platform: pulse_counter
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true
    name: "RPM ventilador 1"
    unit_of_measurement: "RPM"
    accuracy_decimals: 0
    update_interval: 10s

    filters:
      - multiply: 0.5

  - platform: wifi_signal
    name: "WiFi Control Ventiladores"
    update_interval: 60s

button:
  - platform: restart
    name: "Reiniciar Control Ventiladores"

La parte de RPM es opcional. Los ventiladores suelen generar dos pulsos por vuelta en la señal TACH; por eso se aplica multiply: 0.5. Noctua indica que sus ventiladores generan dos pulsos por revolución y que la señal RPM es de tipo colector abierto, por lo que necesita pull-up en la entrada.

Comprobación inicial

Una vez cargado el firmware en el ESP32, en Home Assistant aparecerá una entidad similar a:

fan.control_ventiladores_rack_velocidad_ventiladores

Desde esa entidad se puede probar:

0 %
25 %
50 %
75 %
100 %

En este caso concreto, el 0 % no equivale a parada real, sino a unas 360 rpm. Esto es útil en un rack, porque mantiene una ventilación mínima incluso cuando Home Assistant muestra el ventilador como apagado.

Automatización por temperatura en Home Assistant

Además del control manual, se puede regular la velocidad usando un sensor de temperatura dentro del rack. En este caso se usa un sensor Zigbee colocado detrás de los ventiladores.

Home Assistant proporciona la acción fan.set_percentage, que permite fijar un porcentaje de velocidad en entidades de tipo fan. También se puede disparar una automatización por cambios de estado de una entidad, lo que encaja con un sensor de temperatura que actualiza su valor periódicamente.

Ejemplo de automatización:

alias: "Rack - Regular ventiladores por temperatura"
description: "Ajusta la velocidad de los ventiladores según la temperatura del rack"
mode: restart
triggers:
  - trigger: state
    entity_id: sensor.temperatura_rack
  - trigger: time_pattern
    minutes: "/2"
  - trigger: homeassistant
    event: startactions:
  - variables:
      temp: "{{ states('sensor.temperatura_rack') | float(none) }}"      

fan_entity: fan.control_ventiladores_rack_velocidad_ventiladores
      current_pct: "{{ state_attr('fan.control_ventiladores_rack_velocidad_ventiladores', 'percentage') | int(0) }}"
      target_pct: >-
        {% if temp is none %}
          100
        {% elif temp < 24 %}
          0
        {% elif temp < 26 %}
          20
        {% elif temp < 28 %}
          35
        {% elif temp < 30 %}
          50
        {% elif temp < 32 %}
          65
        {% elif temp < 34 %}
          80
        {% else %}
          100
        {% endif %}

  - choose:
      - conditions:
          - condition: template
            value_template: "{{ temp is none }}"
        sequence:
          - action: fan.set_percentage
            target:
              entity_id: fan.control_ventiladores_rack_velocidad_ventiladores
            data:
              percentage: 100
      - conditions:
          - condition: template
            value_template: "{{ target_pct | int == 0 }}"
        sequence:
          - action: fan.turn_off
            target:
              entity_id: fan.control_ventiladores_rack_velocidad_ventiladores
      - conditions:
          - condition: template
            value_template: >
              {{ is_state(fan_entity, 'off') or ((current_pct | int - target_pct | int) | abs >= 5) }}
        sequence:
          - action: fan.set_percentage
            target:
              entity_id: fan.control_ventiladores_rack_velocidad_ventiladores
            data:
              percentage: "{{ target_pct | int }}"

La curva de funcionamiento queda así:

TemperaturaVelocidad configurada
Sensor no disponible100 %
Menos de 24 ºC0 %
24–26 ºC20 %
26–28 ºC35 %
28–30 ºC50 %
30–32 ºC65 %
32–34 ºC80 %
Más de 34 ºC100 %

Como el sensor está situado justo detrás de los ventiladores, se evita una regulación demasiado nerviosa. La automatización solo cambia la velocidad si hay una diferencia de al menos 5 puntos porcentuales respecto al valor actual.

Problemas encontrados durante el montaje

Durante las pruebas aparecieron varios síntomas extraños:

- Los ventiladores no alcanzaban las RPM máximas.- Con una fuente llegaban a 1500 rpm y con otra solo a 400 rpm.- Al conectar o desconectar la iluminación ARGB cambiaba el comportamiento de los ventiladores.- Al desconectar masas compartidas, los ventiladores se iban a máxima velocidad.

La causa no estaba en ESPHome, sino en alimentación y referencias de masa. Los ventiladores PWM necesitan una masa común con el ESP32 para interpretar correctamente la señal PWM. Si se elimina esa masa común, el PWM deja de tener referencia y el ventilador puede comportarse como si no recibiera señal, y muchos ventiladores PWM pasan a velocidad máxima cuando no hay señal PWM conectada. Noctua también indica que, sin señal PWM conectada, el ventilador funciona a máxima velocidad.

Recomendaciones finales

Para un montaje estable:

1. Alimentar motores con una fuente de 12 V real y estable.
2. No alimentar motores desde el ESP32.
3. Usar cable adecuado para +12 V y GND.
4. Unir GND de fuente 12 V, fuente 5 V y ESP32.
5. No unir los cables TACH de varios ventiladores.
6. Usar 25 kHz como frecuencia PWM.
7. Si se detectan comportamientos raros, probar primero con una fuente de laboratorio.

También es recomendable montar el GND en estrella o con una bornera común robusta, evitando que la corriente de los motores retorne por cables finos o por el propio ESP32.

Conclusión

Con un ESP32 y ESPHome es posible crear un controlador de ventiladores PWM completamente integrado en Home Assistant. El resultado es una ventilación regulable, silenciosa y automatizable, especialmente útil para racks, armarios técnicos o pequeños servidores domésticos.

La clave del montaje no está solo en el YAML, sino en respetar tres principios eléctricos básicos:

12 V estables para motores
GND común para señales
PWM a 25 kHz por el pin dedicado

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *