When riding indoors, we don’t get the natural breeze we’d have outside, so it’s easy to overheat and feel uncomfortable. A smart trainer fan fixes that by adjusting airflow automatically based on how hard we’re working—using things like powerMeter, heart rate, or cadence. This keeps us cool, makes training more enjoyable, and helps us push longer without burning out.
The bad thing is that smart trainer fans on the market are often expensive, typically costing around $300. This project aims to provide an affordable alternative by transforming a standard low-cost fan into a smart trainer fan using a few simple add-ons and easy-to-follow steps. The goal is to make indoor training more comfortable and accessible for everyone without breaking the bank.
Note: To make the DIY process simple and accessible, we chose M5Stack as our starting point. It comes with an integrated ESP32 MCU, WiFi interface, battery, rich libs and offers easy expansion options for adding an infrared receiver and emitter board.
- Continuously monitor data from the Power Meter, Heart Rate Sensor, and Cadence Sensor, and publish these updates to the MQTT server.
- The ESP32 board subscribes to the MQTT server, retrieves the latest sensor data, and—based on pre-programmed logic—controls the fan by turning it on/off or adjusting its speed accordingly.
This project leverages ANT/ANT+ Python library from https://github.com/Tigge/openant. Appreciate the open-source community for making these resources available
- Infrared codes collection and validation
Find or purchase a fan with an infrared remote control, collect, decode, and record its infrared codes with ESP32 + infrared receiver. Typically, the data codes for turning on, turning off, increasing, or reducing the fan speed.
Replay the recorded infrared codes with ESP32 + infrared emitter to validate each code.
in my sample code,
click button A on M5Stack will start to receive and decode the IR code , it will send the code to USBserial, with the irsaver.py on the computer side, it will automatically store the received IR code in a csv file
click button B on M5Stack will replay the saved IR code
- Get ANT+ USB stick
To monitor your heart rate, cadence, and power output during training, a device that can sniff and receive ANT+ signal is needed. In this project, we got a cheap ANT+ USB stick ~$20 from Amazon ( any ANT+ USB stick on Amazon should be Ok ).
- Plug in the ANT+ USB stick, install the openant library and MQTT server
Plug in ANT+ USB stick in a Linux-based laptop/mini PC/Raspberry Pi and ensure ANT+ USB stick is recognized successfully. (Ubuntu 16.04 LTS is the first to have seamless, stable integration with modern ANT+ libraries like OpenAnt. Older systems like Ubuntu 12.04 often required manual kernel module loading)

Following the README in https://github.com/Tigge/openant to prepare and install python libiary, MQTT Server
- Validate the sensor data pub and sub with the MQTT Server by using mqtt docker image
- Run ANT Monitor
The example code: ant_monitor.py only monitors PowerMeter, you could modify it to add support for more sensors easily like Heart Rate, Canadence .. etc ant_monitor will monitor the output of PowerMeter and update it MQTT Server.
- Prepare M5Stack Board
Modify example ESP32 codes (config_example.h) with your recorded infrared codes
Modify example ESP32 codes (config_example.h) with your own network settings
build and update the program (main.ino).
- Put the fan and ESP32 board in front of the trainer, Enjoy your riding :)
M5Stack: https://m5stack.com/ Arduino IDE: https://www.arduino.cc/en/software/