DEV Community

GOROman
GOROman

Posted on

How to Use and Control the M5Stack Fan Module

Introduction

The M5Stack Fan Module v1.1 (STM32F030) is a fan control module that can be used with the M5Stack series. This module makes it easy to add cooling functionality to your projects. In this article, I'll explain how to use the M5Module-Fan library, detail its API, and provide sample code examples.

Image description

Table of Contents

  1. Overview of the M5Stack Fan Module
  2. Installing the M5Module-Fan Library
  3. How to Use the API
  4. Sample Code Explanation
  5. Application Examples

Overview of the M5Stack Fan Module

The M5Stack Fan Module is an I2C-compatible fan module with the STM32F030 microcontroller. Its main features include:

  • Fan control via I2C communication
  • Rotation speed adjustment via PWM control
  • RPM (Revolutions Per Minute) reading functionality
  • Multiple PWM frequency settings (1KHz/12KHz/24KHz/48KHz)
  • Configuration saving to internal flash
  • I2C address modification capability

This module is ideal for projects requiring cooling, air circulation, or temperature management.

Installing the M5Module-Fan Library

For PlatformIO

Add the following dependencies to your platformio.ini file:

lib_deps = 
    https://github.com/m5stack/M5Unified
    https://github.com/m5stack/M5Module-Fan
Enter fullscreen mode Exit fullscreen mode

For Arduino IDE

  1. From the menu, select "Sketch" → "Include Library" → "Manage Libraries..."
  2. Type "M5Module-Fan" in the search bar
  3. Install the displayed library

How to Use the API

Including the Library

#include <m5_module_fan.hpp>
Enter fullscreen mode Exit fullscreen mode

Initializing the Module

M5ModuleFan moduleFan;

// Basic initialization
bool success = moduleFan.begin();

// Initialization with custom I2C settings
bool success = moduleFan.begin(&Wire1, MODULE_FAN_BASE_ADDR, 12, 11, 400000);
// Parameters: Wire, I2C address, SDA pin, SCL pin, I2C speed (Hz)
Enter fullscreen mode Exit fullscreen mode

Main API Functions

Fan Control

// Enable the fan
moduleFan.setStatus(MODULE_FAN_ENABLE);

// Disable the fan
moduleFan.setStatus(MODULE_FAN_DISABLE);

// Get current status
module_fan_status_t status = moduleFan.getStatus();
Enter fullscreen mode Exit fullscreen mode

Setting PWM Frequency

// Set PWM frequency (1KHz, 12KHz, 24KHz, 48KHz)
moduleFan.setPWMFrequency(PWM_1KHZ);  // 1KHz
moduleFan.setPWMFrequency(PWM_12KHZ); // 12KHz
moduleFan.setPWMFrequency(PWM_24KHZ); // 24KHz
moduleFan.setPWMFrequency(PWM_48KHZ); // 48KHz

// Get current PWM frequency setting
module_fan_pwm_freq_t freq = moduleFan.getPWMFrequency();
Enter fullscreen mode Exit fullscreen mode

Setting Duty Cycle

// Set duty cycle (0-100%)
moduleFan.setPWMDutyCycle(80); // Rotate fan at 80% speed

// Get current duty cycle
uint8_t dutyCycle = moduleFan.getPWMDutyCycle();
Enter fullscreen mode Exit fullscreen mode

Getting RPM

// Get current fan rotation speed (RPM)
uint16_t rpm = moduleFan.getRPM();
Enter fullscreen mode Exit fullscreen mode

Getting Signal Frequency

// Get fan output signal frequency
uint16_t signalFreq = moduleFan.getSignalFrequency();
Enter fullscreen mode Exit fullscreen mode

Saving Configuration

// Save current settings to internal flash
moduleFan.saveConfig();
Enter fullscreen mode Exit fullscreen mode

Getting Firmware Version

// Get firmware version
uint8_t version = moduleFan.getFirmwareVersion();
Enter fullscreen mode Exit fullscreen mode

Setting and Getting I2C Address

// Set I2C address (valid range: 0x08-0x77)
uint8_t newAddr = moduleFan.setI2CAddress(0x19);

// Get current I2C address
uint8_t addr = moduleFan.getI2CAddress();
Enter fullscreen mode Exit fullscreen mode

Sample Code Explanation

The following is a basic sample code for controlling the M5Stack Fan Module. This code implements fan status display and button operation for fan control.

#include <M5Unified.h>
#include <m5_module_fan.hpp>

// Fan module instance
M5ModuleFan moduleFan;
// Fan module I2C address
uint8_t deviceAddr = MODULE_FAN_BASE_ADDR;
// Fan duty cycle (0-100%)
uint8_t dutyCycle  = 80;
// Fan operating status
bool fan_status    = true;
// Display canvas
M5Canvas canvas(&M5.Display);

void setup()
{
    M5.begin();
    Serial.begin(115200);
    canvas.createSprite(320, 240);
    canvas.setFont(&fonts::lgfxJapanGothic_24);
    canvas.setTextDatum(top_center);
    canvas.setTextColor(WHITE);

    // Initialize fan module
    // Using Wire1, I2C address=deviceAddr, SDA=12, SCL=11, speed=400000Hz
    while (!moduleFan.begin(&Wire1, deviceAddr, 12, 11, 400000)) {
        Serial.printf("Module FAN Init failed\r\n");
        canvas.drawString("Module FAN Init failed", 160, 120);
        canvas.pushSprite(0, 0);
        delay(1000);
    }

    // Rotate fan at 80% duty cycle
    moduleFan.setPWMDutyCycle(dutyCycle);
    // Set PWM frequency to 1KHz
    moduleFan.setPWMFrequency(PWM_1KHZ);
    // Enable fan
    moduleFan.setStatus(MODULE_FAN_ENABLE);
}

void loop()
{
    // Current PWM frequency setting index
    int pwm_config_index  = moduleFan.getPWMFrequency();
    // PWM frequency string representation
    String pwm_config_str = "";

    // Convert PWM frequency index to string
    switch (pwm_config_index) {
        case PWM_1KHZ:
            pwm_config_str = "1KHz";
            break;
        case PWM_12KHZ:
            pwm_config_str = "12KHz";
            break;
        case PWM_24KHZ:
            pwm_config_str = "24KHz";
            break;
        case PWM_48KHZ:
            pwm_config_str = "48KHz";
            break;
    }

    // Update screen display
    canvas.setCursor(0, 10);
    canvas.clear();
    // Display fan operating status
    canvas.printf("Work Status    :%s\r\n", moduleFan.getStatus() == MODULE_FAN_ENABLE ? "RUNNING" : "STOP");
    // Display PWM frequency
    canvas.printf("PWM  Frequency :%s\r\n", pwm_config_str.c_str());
    // Display duty cycle
    canvas.printf("PWM  Duty Cycle:%d%%\r\n", moduleFan.getPWMDutyCycle());
    // Display rotation speed (RPM)
    canvas.printf("RPM            :%drpm\r\n", moduleFan.getRPM());
    canvas.pushSprite(0, 0);

    // Update button state
    M5.update();
    auto t = M5.Touch.getDetail();

    // If button A is pressed: Toggle fan ON/OFF
    if (M5.BtnA.wasPressed()) {
        fan_status = !fan_status;
        if (fan_status) {
            moduleFan.setStatus(MODULE_FAN_ENABLE);
        } else {
            moduleFan.setStatus(MODULE_FAN_DISABLE);
        }
    }

    // If button B is pressed: Decrease duty cycle by 10%
    if (M5.BtnB.wasPressed()) {
        dutyCycle -= 10;
        if (dutyCycle < 0) {
            dutyCycle = 100;
        }
        moduleFan.setPWMDutyCycle(dutyCycle);
    }

    // If button C is pressed: Increase duty cycle by 10%
    if (M5.BtnC.wasPressed()) {
        dutyCycle += 10;
        if (dutyCycle > 100) {
            dutyCycle = 0;
        }
        moduleFan.setPWMDutyCycle(dutyCycle);
    }

    delay(10);
}
Enter fullscreen mode Exit fullscreen mode

Code Explanation

Initialization Part (setup function)

  1. Initialize M5Stack and display settings
  2. Initialize fan module (specify Wire1, I2C address, SDA/SCL pins, communication speed)
  3. Initial settings:
    • Duty cycle: 80%
    • PWM frequency: 1KHz
    • Fan status: Enabled (rotating)

Main Loop (loop function)

  1. Get current PWM frequency setting and convert to corresponding string
  2. Update screen display:
    • Fan operating status (RUNNING/STOP)
    • PWM frequency (1KHz/12KHz/24KHz/48KHz)
    • Duty cycle (0-100%)
    • Current rotation speed (RPM)
  3. Handle button operations:
    • Button A: Toggle fan ON/OFF
    • Button B: Decrease duty cycle by 10%
    • Button C: Increase duty cycle by 10%

Application Examples

Temperature Control System

You can build a system that automatically adjusts fan speed based on temperature by combining it with a temperature sensor.

#include <M5Unified.h>
#include <m5_module_fan.hpp>

M5ModuleFan moduleFan;
float temperature;

void setup() {
    M5.begin();
    moduleFan.begin(&Wire1, MODULE_FAN_BASE_ADDR, 12, 11, 400000);
    moduleFan.setPWMFrequency(PWM_1KHZ);
    moduleFan.setStatus(MODULE_FAN_ENABLE);
}

void loop() {
    // Get temperature from temperature sensor (example)
    temperature = M5.Imu.getTemp();

    // Adjust fan speed based on temperature
    if (temperature < 25.0) {
        // Below 25°C: Fan off
        moduleFan.setStatus(MODULE_FAN_DISABLE);
    } else if (temperature < 30.0) {
        // 25-30°C: Low speed (30%)
        moduleFan.setStatus(MODULE_FAN_ENABLE);
        moduleFan.setPWMDutyCycle(30);
    } else if (temperature < 35.0) {
        // 30-35°C: Medium speed (60%)
        moduleFan.setStatus(MODULE_FAN_ENABLE);
        moduleFan.setPWMDutyCycle(60);
    } else {
        // Above 35°C: High speed (100%)
        moduleFan.setStatus(MODULE_FAN_ENABLE);
        moduleFan.setPWMDutyCycle(100);
    }

    // Display information
    M5.Display.clear();
    M5.Display.setCursor(0, 0);
    M5.Display.printf("Temperature: %.1f C\n", temperature);
    M5.Display.printf("Fan Speed: %d%%\n", moduleFan.getPWMDutyCycle());
    M5.Display.printf("RPM: %d\n", moduleFan.getRPM());

    delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Controlling Multiple Fans

You can individually control multiple fan modules by changing the I2C address.

#include <M5Unified.h>
#include <m5_module_fan.hpp>

M5ModuleFan fan1;
M5ModuleFan fan2;

void setup() {
    M5.begin();

    // Initialize fan 1 (default address)
    fan1.begin(&Wire1, MODULE_FAN_BASE_ADDR, 12, 11, 400000);

    // Initialize fan 2 (change address to 0x19)
    fan2.begin(&Wire1, 0x19, 12, 11, 400000);

    // Enable both fans
    fan1.setStatus(MODULE_FAN_ENABLE);
    fan2.setStatus(MODULE_FAN_ENABLE);

    // Different speed settings
    fan1.setPWMDutyCycle(50);  // Fan 1: 50%
    fan2.setPWMDutyCycle(80);  // Fan 2: 80%
}

void loop() {
    // Display status
    M5.Display.clear();
    M5.Display.setCursor(0, 0);
    M5.Display.printf("Fan 1 - Speed: %d%%, RPM: %d\n", 
                     fan1.getPWMDutyCycle(), fan1.getRPM());
    M5.Display.printf("Fan 2 - Speed: %d%%, RPM: %d\n", 
                     fan2.getPWMDutyCycle(), fan2.getRPM());

    delay(1000);
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

The M5Stack Fan Module is a fan module that can be easily controlled using I2C communication. By using the M5Module-Fan library, you can easily implement functions such as enabling/disabling the fan, adjusting rotation speed, and getting rotation speed.

This module can be used in various projects such as electronic device cooling, air circulation, and temperature management. In particular, by combining it with a temperature sensor, you can build an intelligent cooling system.

Reference Links

Top comments (0)