Firefly Open Source Community

   Login   |   Register   |
New_Topic
Print Previous Topic Next Topic

[General] Stock fan going full tilt on idle: software solution

66

Credits

0

Prestige

24

Contribution

registered members

Rank: 2

Credits
66

【General】 Stock fan going full tilt on idle: software solution

Posted at 7/13/2022 02:06:38      View:1567 | Replies:1        Print      Only Author   [Copy Link] 1#
If you are like me and your fan on ROC-3588S-PC goes full speed when the board is idle then in this thread you are going to find a way to fix it:

I have the v0.1 revision of the board, 3 pin fan header, fan and heatsink integrated together. OS - Ubuntu Minimal. When the board is powered up the fan doesn't spin, but as soon as the OS boots up the fan starts spinning full speed.  This is not really what I want - below 50C there's no need to spin the fan at all, so I started digging, and this is what I have found:

There's a systemd service responsible for fan control:
  1. systemctl status firefly-fan.service
Copy the code

It clearly works not the way I want so I checked out the code of the service. For ROC-3588S-PC in the end it starts /usr/bin/firefly_fan_control which is a binary executable. And there's no manual for this firefly_fan_control.

I have quickly reverse engineered this thing and figured out a way to control this fan the way I want:
  1. echo 0 > /sys/class/hwmon/hwmon1/pwm1
Copy the code

This is how the fan speed is set for v0.1 board. 0 = full tilt, 255 = stop.

  1. cat /sys/class/thermal/thermal_zone*/temp
Copy the code

This is how the firefly_fan_control gets the temperature reading. You can take all thermal zones and average, or pick one of them, it's up to you.

Knowing all that you can get the fan curve that you like disabling firefly_fan.service and coding up your own fan control script that gets temperature and writes the desired fan speed as suggested above. I will put my script in the next post after I figure out good parameters for it.

Final thoughts:
A typical PWM fan goes full tilt when there's no PWM signal (for safety reasons I suppose). The fact that for board v0.1 the fan doesn't start spinning right after the board is powered suggests that on v0.1 the fan PWM control is not done as it's done usually. Probably in the board v1.0 with the 4 pin fan connector the fan control is implemented as it usually is and as a result we get an issue with the fan on 0.1 board, caused by software not being aware of the difference between 0.1 and 1.0 boards.

Suggestion to Firefly devs: maybe you add an if branch in firefly_fan_control for v0.1 board to fix this issue or make fan control a human readable script so that people without executable files parsing skill can play with the fan? I certainly know that a lot of people like to setup custom fan curves, they gonna love it.

However even if firefly does nothing about it people with 0.1 board can now fix this issue and everyone who wants a custom fan curve can do that.
Reply

Use props Report

66

Credits

0

Prestige

24

Contribution

registered members

Rank: 2

Credits
66
Posted at 7/13/2022 03:36:03        Only Author  2#
Last edited by vga84 In 7/13/2022 04:45 Editor

This is fan control script. Location:  /usr/local/bin/fanctl
  1. #!/usr/bin/python3

  2. import time
  3. import sys

  4. TEMP_MIN = 45
  5. FAN_LEVELS = {"off" : 255, "min" : 195, "max" : 0}
  6. TEMP_MAX = 75
  7. HYSTERESIS = 10
  8. TEMP_OFF = TEMP_MIN - HYSTERESIS

  9. def soc_temp():
  10.     soc_temperature_file = "/sys/class/thermal/thermal_zone0/temp"
  11.     with open(soc_temperature_file, 'r') as file:
  12.         data = file.read().rstrip()
  13.     return float(data) / 1000

  14. def fan_speed(temperature):
  15.     weight = (temperature - TEMP_MIN) / (TEMP_MAX - TEMP_MIN)
  16.     fan_speed = FAN_LEVELS["min"] + weight * (FAN_LEVELS["max"] - FAN_LEVELS["min"])
  17.     if temperature <= 45:
  18.         fan_speed = FAN_LEVELS["min"]
  19.     elif temperature >= 75:
  20.         fan_speed = FAN_LEVELS["max"]
  21.     return int(fan_speed)

  22. def set_fan_speed(speed):
  23.     fan_speed_file = "/sys/class/hwmon/hwmon1/pwm1"
  24.     speed = 0 if speed < 0 else 255 if speed > 255 else speed
  25.     with open(fan_speed_file, 'w') as file:
  26.         file.write(str(speed))

  27. def main():
  28.     lpf_weight = 0.7  # linear filter to reduce speed jitter
  29.     temperature_delay = 35
  30.     fan_status = False
  31.     while True:
  32.         temperature = \
  33.             (1 - lpf_weight) * soc_temp() + lpf_weight * temperature_delay
  34.         speed = fan_speed(temperature)   
  35.         #print(f"Temp: {temperature:.2f}; Speed: {speed}, Fan Status: {fan_status}")
  36.         if temperature > TEMP_MIN:
  37.             fan_status = True
  38.         elif temperature < TEMP_OFF:
  39.             speed = FAN_LEVELS["off"]
  40.             fan_status = False
  41.         else:
  42.             speed = speed if fan_status else FAN_LEVELS["off"]        
  43.         set_fan_speed(speed)
  44.         temperature_delay = temperature
  45.         #sys.stdout.flush()
  46.         time.sleep(1)

  47. if __name__ == "__main__":
  48.     try:
  49.         main()
  50.         sys.exit(0)
  51.     except Exception as e:
  52.         print(f"ERROR: {str(e)}")
  53.         sys.exit(1)     # this will show up in systemd logs as service failure
Copy the code


This is fan control unit file. Location: /etc/systemd/system/fanctl.service
  1. [Unit]
  2. Description=Custom fan control for ROC-3588S-PC

  3. [Service]
  4. Type=simple
  5. ExecStart=/usr/bin/python3 /usr/local/bin/fanctl

  6. [Install]
  7. WantedBy=multi-user.target
Copy the code
After placing this files in suggested location do the following as root:
  1. chown root:root /usr/local/bin/fanctl
  2. chmod +x /usr/local/bin/fanctl
  3. systemctl disable firefly-fan.service
  4. systemctl enable fanctl.service
  5. reboot
Copy the code

Enjoy the fan that is silent when the SOC is idle! Current script settings are:
* Fan is off when SOC is < 45C
* There is a 10C hysteresis at 45C to avoid fan on/off jitter
* Fan is full tilt when SOC is >= 75C
* Temperature is filtered with a linear filter to make fan control more smooth


You can change them as you like or introduce your own fan control system. In case you find any issues with the script please let me know here in this topic.
已有 1评分Contribution +12 Pack up reason
BrokenStorie + 12 Thank you!

View all ratings

Reply

Use props Report

You need to log in before you can reply Login | Register

This forum Credits Rules

Quick Reply Back to top Back to list