PWM Fan control with ESP32

Hello everyone,

I’ve just received my (first) ESP32 and trying to use it as a controller for a 120mm PWM fan in my network cabinet.

I took example on this topic using ESPHome with ledc output. What changes in my case is that my fan is a PWM PC fan (4pin, 12V) so I assume i don’t need the MOS Module, right ?

Here’s my diagram :

Here’s my ESPHome config :

  name: fans
  platform: ESP32
  board: nodemcu-32s

  ssid: "XXXXXX"
  password: "XXXXXX"

# Enable logging

# Enable Home Assistant API
  password: "XXXXXX"

  password: "XXXXXX"

  - platform: ledc
    pin: GPIO12
    frequency: 10000 Hz
    id: cabfan

  - platform: speed
    output: cabfan
    name: "Network Cabinet Fan"

The upload is successful and I see my fan.network_cabinet_fan in Home Assistant.
When I change speed, I can see the ESP32’s onboard LED flash, I see logs in ESPHome but nothing is happening on the fan, it stays at full speed.

I unfortunately don’t have an oscilloscope (Or LED) to check if the PWM signal is good or not. When checking with a multimeter, I can see the voltage between the ESP Pins G12 and GND as following :
Low speed : -2.10V ±0.05V
Medium speed : 1.0V ±0.05V
High speed : 0V ±0.2V

These values are with the ESP’s GND, so do I have to connect ESP32’s GND to PSU’s GND ?
I tried to do it but in the logs I’m seeing this :

[13:44:49]Guru Meditation Error: Core  0 panic'ed (IllegalInstruction). Exception was unhandled.
[13:44:49]Memory dump at 0x400fdcf8: ffffffff ffffffff 3df03dd4
[13:44:49]Core 0 register dump:
[13:44:49]PC      : 0x400fdcff  PS      : 0x00060430  A0      : 0x8010a1e3  A1      : 0x3ffb5ef0
e[32mINFO Need to fetch platformio IDE-data, please stand bye[0m
e[32mINFO Running:  platformio run -d fans -t idedatae[0m
[13:44:50]A2      : 0x3ffcceb8  A3      : 0x3ffd368c  A4      : 0x3ffb5f50  A5      : 0x0000007f
[13:44:50]A6      : 0x3ffd3831  A7      : 0x3ffd370a  A8      : 0x3ffd3833  A9      : 0x01f25000
[13:44:50]A10     : 0x01f25000  A11     : 0x00001000  A12     : 0x00000016  A13     : 0x3ffd386c
[13:44:50]A14     : 0x0000e815  A15     : 0x00000007  SAR     : 0x00000020  EXCCAUSE: 0x00000000
[13:44:50]EXCVADDR: 0x00000000  LBEG    : 0x4000c46c  LEND    : 0x4000c477  LCOUNT  : 0x00000000
[13:44:50]Backtrace: 0x400fdcff:0x3ffb5ef0 0x4010a1e0:0x3ffb5f40 0x4010ad71:0x3ffb6080 0x4014f279:0x3ffb60a0 0x4008f7ce:0x3ffb60f0 0x40088d95:0x3ffb6130
e[33mWARNING Found stack trace! Trying to decode ite[0m

Also, in the logs I see the following speeds being sent :

[13:47:42][D][]: Setting speed: 0.33
[13:47:45][D][]: Setting speed: 0.66
[13:47:47][D][]: Setting speed: 1.00

Do I have to change them from 0 to 255 instead of 0 to 1 ?

Thanks for your help

If you are powering the esp from a different source than the fan then yes. You need a common ground as a reference for the pwm signal.

It’s more than just tying the grounds together. I think the PWM signal has to be at the same voltage as VCC. So you’d have to step up the ESP32 output to VCC.

after you make sure the grounds are connected, are you using the correct pin for PWM and not accidentally sending the PWM signal to the tach wire? Silly question I know, but sometimes it’s the obvious that gets overlooked.

Grounds have been connected, no change.

Your first post made me check again about PWM signal, it should be 5V. That’s good in my case.
For the pin, yes it’s the right one. I’ve checked under the fan label, the cable connection to the board is labeled PWM.

The ESP outputs 3.3v. Not quite enough for 5v TTL (3.5v min).

Dang, wasn’t aware of that. While powering with 5V I assumed the output was 5V…
I guess I’ll have to use a level shifter.

Yeah there’s an on board voltage regulator that drops the 5 to 3.3 for the ESP.

I’ve received my level shifter today and it works as expected. Well, not at first because there is a pin on my ESP32 board labeled GND but should be labeled CMD … changed ground pin and it works !
Only issue is that levels are backwards : if I set “high” on HA the fan stops and if I set “off” the fan is at full power. Pretty sure that’s not hard to change.

Sharing the diagram in case someone wants to reproduce :

Thanks for the help.


Thank you for sharing the info. What level shifter did you get ? How’s your fan running ?

In my case, using 4pin fans (dell/server) I have not needed a level shifter, datasheet for my fans say they want 3.3v PWM at 25Khz (above human hearing) which esp32 can do but esp8266 cannot.
You need to manually set PWM frequency in esphome to 25000hz, some fans also require min_pwm 0.3 (30%) to get them going from a dead stop

Beware the tachometer output is usually pulsed 12V, which will probably kill ESP without a voltage divider circuit, so triple check you have everything hooked up properly before applying power

1 Like

Great post! I want to make exactly that - control a 12V PWM fan with ESP from HA. One question: did someone solve the inverted levels? Why are the levels backwards?

1 Like

Default behaviour of the fans when they don’t recieve a PWM signal (0% duty cycle) they failsafe into a full speed setting.
Using LEDC the fans work as expected, but again I’m not using level shifters and always send them a minimum PWM value so they start reliably and don’t go into failsafe

1 Like

I assembled this thing today. Used Arctic PWM fan + level shifter + voltage regulator which lowers 12V to 5V to power the ESP32 and provides the reference voltage for the level shifter. It mostly works correctly. No inverted control in HA, but there’s one problem: when I set the speed to 0 in HA the fan still spins at a low speed. It doesn’t stop. Any ideas?? I don’t want to add a relay to cut the power off.
What can be wrong?

Hey there, I came across this thread by chance. Apparently, some fans can’t be turned off using PWM and just have a minimum speed. Noctua can be turned off.

Hello together, since reddit is currently not working and I cant see my post there I’m also posting here. I hope here are some ESP experts around which could help me out.

This is my “first” big ESP project. 3 years ago I build BRUHs Multisensor but thats basically just putting things together.

What I want to archive is basically this but with temperature & PWM controlled fans monitored by HomeAssistant

r/homeassistant - Need help building a radiator booster with ESP32 and PC fans

I’m by far no expert in this topic but I hope that I have enough knowlegde to archive this.This was my fist time using fritzing so please dont blame me :slight_smile:

That’s what I currently have. But I’m unsure if its wired correctly. The GPIO Pins were randomly connected because I dont know which pins I must connect.

r/homeassistant - Need help building a radiator booster with ESP32 and PC fans

The thing should be powered by a 12V power adapter. A Buck converter will step this down to 5V to power the ESP32. The mosfet driver is just a placeholder (couldnt find a proper one in fritzing) the correct should be the one in the picture. The DS18B20 will measure the incomming water temperature of the radiator. When there are high temperatures, the fans should spin up. Since I’m going to use Arctic fans which cant be turned off via PWM I hooked up a relais to cut the 12V to the fan.

So, my questions are: Is this wired up correctly or will the hole thing explode?

And: Which pins must be used to control the relais, monitor the sensor and sent the PWM signal?

Do you have other recommendations how to archiv this? The mosfet driver could possibly replaced by a level shifter and PWM fans but i haven’t found any informations about hz or voltage for the PWM signal of the Arctic fans.

1 Like

Controlling your fan by true PWM is more efficient than having a mosfet controlling the power to the fan. You only need a 3.3V to 5v logic convertor (cheap transistor(s) and some resistors). Fan PWM is 5V. You can also connect Tach-wire to ESP32 as input with pulse_counter sensor to get RPM-readings.

PWM-fan: Ground, 12V, Tach, PWM. Google “Pinout PWM fan” ,

logic level convertor something like; Simple Level Shifter With Transistors (3.3V-5V) Probably you can use a single 2n3904 BUT you have to invert PWM signal. Possible with ESPHome as property for output component. So get rid of first transistor in schematic.


I’ve got a question concerning speed fan component within ESPHome. When configuring this component in ESPHome Home Assistant only exposes a toggle button. I’m missing a slider-control.

Within homeassistant MQTT-topics this component config is;

  "speed_level_command_topic":  "home/esph_pwm_fans/fan/fan_esph_pwm_fans/speed_level/command",
  "speed_level_state_topic":    "home/esph_pwm_fans/fan/fan_esph_pwm_fans/speed_level/state",
  "spd_cmd_t":                  "home/esph_pwm_fans/fan/fan_esph_pwm_fans/speed/command",
  "spd_stat_t":                 "home/esph_pwm_fans/fan/fan_esph_pwm_fans/speed/state",
  "name":                       "fan_esph_pwm_fans",
  "stat_t":                     "home/esph_pwm_fans/fan/fan_esph_pwm_fans/state",
  "cmd_t":                      "home/esph_pwm_fans/fan/fan_esph_pwm_fans/command",
  "avty_t":                     "home/esph_pwm_fans/status",
  "uniq_id":                    "ESPfanfan_esph_pwm_fans",
  "dev":                        {
    "ids":                          "246f28ae0bd4",
    "name":                         "esph_pwm_fans",
    "sw":                           "esphome v2021.11.4 Dec  6 2021, 22:09:06",
    "mdl":                          "esp32doit-devkit-v1",
    "mf":                           "espressif"
  - platform: ledc
      number: GPIO23
      inverted: false
      mode: OUTPUT
    id: oid1
    frequency: 25000 Hz

  - platform: speed
    output: oid1
    name: ${fan_name}
    id: ${fan_id}
    speed_count: 100

When submitting a value (between 0 and 100) to speed_level_command_topic (in MQTT Explorer) the FAN Speed is controllable. Why doesn’t Home Assistant show Slider-control?

To reply on my own question. It appears ESPHome dropped Speed fan MQTT support as Home Assistant changed inner workings. Moving to API websocket communication Speed fan slider will be available. Maybe ESPhome is going to fix MQTT support for Speed Fan.

I got the official answer from Noctua:
“5V PWM fan can easily be driven DIRECTLY from ESP32, 3.3V logic is enough. Also there is no need for additional transistor to amplify the PWM signal”.

Actually I have done the power supply with 3 fans - all are 5V PWM, 120mm and 60mm - all are driven directly from GPIOs from ESP32 without any issue.