Enabling Automatic Temperature Fan Control on VIM1 (Armbian) via I2C

Hi everyone, Prageeth here.

I am currently using Khadas VIM1 boards for a custom hardware project. I recently upgraded to Armbian Linux (6.12.58-current-meson64) and ran into a challenge getting the cooling fan to work automatically. I wanted to share my troubleshooting experience and the final solution in case anyone else runs into the same issue.

Hardware Used

For this setup, I am using the official Khadas cooling accessories:

The Problem

When plugging the cooling fan into the fan header, it wouldn’t spin up automatically under load. I initially tried exporting standard PWM chips (/sys/class/pwm/pwmchip0) and using standard Linux utilities like fancontrol and pwmconfig, but the system would throw “Device busy” or “Permission denied” errors, or simply fail to spin the fan.

The Discovery

After digging into the VIM1 schematics (v14), I realized why standard Linux PWM controls were failing. The FAN_PWM header is not directly connected to the S905X processor’s PWM pins.

Instead, it is wired to the onboard STM8S MCU (U20). The S905X communicates with this MCU via I2C (I2C_B). Therefore, to control the fan, you have to bypass standard PWM drivers and send direct hex commands to the MCU over the I2C bus.

Here is the mapping for the Khadas VIM1 MCU:

  • I2C Bus: 1

  • MCU Address: 0x18

  • Fan Control Register: 0x88

  • Values: 0x00 (Off), 0x01 (Low Speed), 0x03 (High Speed)

The Solution: A Custom Thermostat Script

To get the fan acting normally, I wrote a lightweight bash script and systemd service to monitor the CPU temperature and send the correct I2C commands. It uses a 3-stage logic with built-in hysteresis to prevent the fan from turning on and off rapidly.

Step 1: Install Dependencies

You will need i2c-tools to talk to the MCU.

Bash

sudo apt update
sudo apt install i2c-tools -y

Step 2: Create the Control Script

Create a new script file:

Bash

sudo nano /usr/local/bin/vim1_cooler.sh

Paste in the following code. (This configuration turns the fan off below 50°C, runs it at low speed at 60°C, and kicks it into high speed at 70°C).

Bash

#!/bin/bash

# --- Thermal Thresholds (Millidegrees) ---
MAX_T=70000   # 70°C - Full Speed
MID_T=60000   # 60°C - Start Fan / Low Speed
MIN_T=50000   # 50°C - Turn Off

# --- I2C Hex Values ---
VAL_STOP=0x00
VAL_SLOW=0x01      
VAL_FAST=0x03     

# --- Hardware Map ---
I2C_B=1
I2C_A=0x18
I2C_R=0x88

TEMP_SRC="/sys/class/thermal/thermal_zone0/temp"
MODE=0

# Ensure fan is off at start
i2cset -y $I2C_B $I2C_A $I2C_R $VAL_STOP
echo "Cooling daemon active."

while true; do
    CUR_T=$(cat $TEMP_SRC)
    
    # CASE 1: > 70C -> FULL SPEED
    if [ "$CUR_T" -ge "$MAX_T" ]; then
        if [ "$MODE" -ne 3 ]; then
            i2cset -y $I2C_B $I2C_A $I2C_R $VAL_FAST
            MODE=3
        fi

    # CASE 2: > 60C -> LOW SPEED
    elif [ "$CUR_T" -ge "$MID_T" ]; then
        if [ "$MODE" -ne 1 ]; then
            i2cset -y $I2C_B $I2C_A $I2C_R $VAL_SLOW
            MODE=1
        fi

    # CASE 3: < 50C -> TURN OFF
    elif [ "$CUR_T" -le "$MIN_T" ]; then
        if [ "$MODE" -ne 0 ]; then
            i2cset -y $I2C_B $I2C_A $I2C_R $VAL_STOP
            MODE=0
        fi
    fi

    # Check every 3 seconds
    sleep 3
done

Save the file. Make sure to fix the permissions and line endings so systemd can execute it:

Bash

sudo chmod +x /usr/local/bin/vim1_cooler.sh
sudo sed -i 's/\r$//' /usr/local/bin/vim1_cooler.sh

Step 3: Create the Systemd Service

To make this run automatically on boot, create a service file:

Bash

sudo nano /etc/systemd/system/vim1-cooler.service

Paste the following:

Ini, TOML

[Unit]
Description=VIM1 I2C Cooling Daemon
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/local/bin/vim1_cooler.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Finally, enable and start the service:

Bash

sudo systemctl daemon-reload
sudo systemctl enable vim1-cooler.service
sudo systemctl start vim1-cooler.service

You can check sudo systemctl status vim1-cooler.service to ensure it is running without errors.

I hope this saves some time for anyone else building projects on Armbian with the VIM1!

Cheers, Prageeth

3 Likes

Hello @Prageeth_Malinga

Thanks for your guidance. :wink: