Macs Fan Control 1.4.12
MacPro5,1
CPU: Intel(R) Xeon(R) CPU X5690 @ 3.47GHz [100]
GPU: Radeon RX 480 [active], Radeon RX 480
macOS 10.15.2
Fans:
PCI-min{800}curr{798}max{4500}mode{2,TA0P,32,40}
PS-min{600}curr{914}max{2800}mode{2,Tp1C,38,48}
EXHAUST-min{600}curr{599}max{2800}mode{0}
INTAKE-min{600}curr{1864}max{2800}mode{2,TN0D,53,63}
BOOSTA-min{800}curr{3168}max{5200}mode{2,TN0D,53,63}
BOOSTB-min{800}curr{1113}max{5200}mode{0}
TempSensors:
TA0P (Ambient) - 31.625, 31.625
TCAC (CPU A core from PCECI) - 41.3125, 58.6875
TCAD (CPU A Diode) - 43.25, 43.25
TCAG () - 80, 80
TCAH (CPU A HeatSink) - 39.75, 39.75
TCAS () - 39.75, 39.75
TCBC (CPU B core from PCECI) - 33.625, 66.375
TCBD (CPU B Diode) - 36.875, 36.875
TCBG () - 80, 80
TCBH (CPU B HeatSink) - 32.875, 32.875
TCBS () - 33, 33
TH1F () - 32.5391, 32.5391
TH1P (Drive Bay 0) - 32.5, 32.5
TH1V () - 35.2227, 35.2227
TH2F () - 34.1992, 34.1992
TH2P (Drive Bay 1) - 34.375, 34.375
TH2V () - 33.4062, 33.4062
TH3F () - 33.9375, 33.9375
TH3P (Drive Bay 2) - 34, 34
TH3V () - 32.8633, 32.8633
TH4F () - 33.082, 33.082
TH4P (Drive Bay 3) - 33.125, 33.125
TH4V () - 35.3047, 35.3047
THPS () - 35.2969, 35.2969
THTG () - 58, 58
TM1P (DIMM Proximity 1) - 36.5, 36.5
TM2P (DIMM Proximity 2) - 37.375, 37.375
TM3P (DIMM Proximity 3) - 38.625, 38.625
TM4P (DIMM Proximity 4) - 38.25, 38.25
TM5P (DIMM Proximity 5) - 38.5, 38.5
TM6P (DIMM Proximity 6) - 40.625, 40.625
TM7P (DIMM Proximity 7) - 37.5, 37.5
TM8P (DIMM Proximity 8) - 29.5, 29.5
TMA1 () - 40.75, 40.75
TMA2 () - 42.5, 42.5
TMA3 () - 42.75, 42.75
TMA4 () - 42.25, 42.25
TMB1 () - 34, 34
TMB2 () - 33.5, 33.5
TMB3 () - 33.75, 33.75
TMB4 () - 32, 32
TMHS () - 42.75, 42.75
TMLS () - 32, 32
TMPS () - 42.75, 42.75
TMPV () - 40.0859, 40.0859
TMTG () - 75, 75
TN0D (IOH Diode) - 59.25, 59.25
TN0H (IOH HeatSink) - 47.125, 47.125
TNTG () - 65, 65
Te1F () - 128, 128
Te1P (PCIE Ambient) - 34.375, 34.375
Te1S () - 128, 128
Te2F () - 129, 129
Te2S () - 129, 129
Te3F () - 129, 129
Te3S () - 129, 129
Te4F () - 129, 129
Te4S () - 129, 129
Te5F () - 129, 129
Te5S () - 129, 129
TeGG () - 85, 85
TeGP () - 0, 0
TeRG () - 60, 60
TeRP () - 0, 0
Tp0C (PSMI Supply AC/DC Supply 1) - 39.8125, 39.8125
Tp1C (PSMI Supply AC/DC Supply 2) - 40.3906, 40.3906
TpPS () - 40.3906, 40.3906
TpTG () - 90, 90
Last active
February 15, 2026 18:46
-
-
Save startergo/ea6b825efd9846d989874bed1675a1e9 to your computer and use it in GitHub Desktop.
MacfansControl cMP5,1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #/bin/bash | |
| ###################################################################################################################### | |
| # Bash script to control the three fans for an iMac 10,1 (late 2009) Intel Core Duo. | |
| # Save somewhere like /usr/local/bin/fancontrol.sh | |
| # sudo chmod 755 /usr/local/bin/fancontrol.sh | |
| ###################################################################################################################### | |
| ###################################################################################################################### | |
| # To read internal drive temperature need to load the drivetemp module: | |
| # Create file /etc/modules-load.d/drivetemp.conf with the text | |
| # drivetemp | |
| # For initial load: | |
| # sudo modprobe drivetemp | |
| ###################################################################################################################### | |
| ###################################################################################################################### | |
| # Create systemd service by writing /etc/systemd/system/fancontrol.service: | |
| # | |
| # [Unit] | |
| # Description=Control iMac fans | |
| # | |
| # [Service] | |
| # Type=simple | |
| # ExecStart=/bin/bash /usr/local/bin/fancontrol.sh | |
| # | |
| # [Install] | |
| # WantedBy=multi-user.target | |
| # | |
| # Then | |
| # sudo systemctl enable fancontrol.service | |
| # sudo systemctl start fancontrol.service | |
| ###################################################################################################################### | |
| ###################################################################################################################### | |
| # The optical drive fan will be controlled by the GPU die temperature. | |
| # The hard disk fan will be controlled by the SSD and memory temperatures, whichever is higher within its limits. | |
| # The CPU fan will be controlled by the power supply and CPU core temperatures, whichever is higher within its limits. | |
| ###################################################################################################################### | |
| ###################################################################################################################### | |
| # *_HIGH_TEMP variables contain the temperature in Celsius when the fan RPM will start to rise above the minimum. | |
| # *_MAX_TEMP variables contain the temperature in Celsius when the fan will be running at maximum RPM. | |
| ###################################################################################################################### | |
| ###################################################################################################################### | |
| # The sensors available on other iMac models will probably be different. Find the sensor names with: | |
| # for sensor in /sys/devices/platform/applesmc.768/*_label; do echo -n $sensor " "; cat "$sensor"; done | |
| # then an Internet search to identify what they mean. | |
| ###################################################################################################################### | |
| # Initial sleep so devices are present. I'm sure there's a better way of doing this. | |
| sleep 10 | |
| # GPU die temp | |
| GPU_TEMP_SENSOR=/sys/devices/platform/applesmc.768/temp6_input | |
| GPU_HIGH_TEMP="82" | |
| GPU_MAX_TEMP="100" | |
| # Memory temp | |
| MEM_TEMP_SENSOR=/sys/devices/platform/applesmc.768/temp26_input | |
| MEM_HIGH_TEMP="65" | |
| MEM_MAX_TEMP="85" | |
| # SSD temp | |
| # If you use /sys/class/hwmon you might find removable drives plugged in at boot time instead of the internal drive | |
| # so look for ATA devices instead. Find the sensor path using: | |
| # find /sys/devices -name hwmon -type d | grep ata1 | |
| SSD_TEMP_SENSOR_PATH="$(grep -l "drivetemp" /sys/devices/pci0000:00/0000:00:0b.0/ata1/host0/target0:0:0/0:0:0:0/hwmon/hwmon*/name)" | |
| SSD_TEMP_SENSOR="${SSD_TEMP_SENSOR_PATH%/*}/temp1_input" | |
| SSD_HIGH_TEMP="44" | |
| SSD_MAX_TEMP="65" | |
| # PSU temp | |
| PSU_TEMP_SENSOR=/sys/devices/platform/applesmc.768/temp29_input | |
| PSU_HIGH_TEMP="84" | |
| PSU_MAX_TEMP="100" | |
| # CPU temps | |
| CPU_TEMP_SENSOR_PATH="$(grep -l "coretemp" /sys/class/hwmon/hwmon*/name)" | |
| CPU1_TEMP_SENSOR="${CPU_TEMP_SENSOR_PATH%/*}/temp2_input" | |
| CPU2_TEMP_SENSOR="${CPU_TEMP_SENSOR_PATH%/*}/temp3_input" | |
| CPU_HIGH_TEMP="55" | |
| CPU_MAX_TEMP="100" | |
| # Fan devices | |
| FAN_ODD_DEVICE=/sys/devices/platform/applesmc.768/fan1_ | |
| FAN_ODD_MIN=$(<"${FAN_ODD_DEVICE}min") | |
| FAN_ODD_MAX=$(<"${FAN_ODD_DEVICE}max") | |
| FAN_HDD_DEVICE=/sys/devices/platform/applesmc.768/fan2_ | |
| FAN_HDD_MIN=$(<"${FAN_HDD_DEVICE}min") | |
| FAN_HDD_MAX=$(<"${FAN_HDD_DEVICE}max") | |
| FAN_CPU_DEVICE=/sys/devices/platform/applesmc.768/fan3_ | |
| FAN_CPU_MIN=$(<"${FAN_CPU_DEVICE}min") | |
| FAN_CPU_MAX=$(<"${FAN_CPU_DEVICE}max") | |
| # Steps for fan when over the high temperature | |
| GPU_FAN_STEP=$((($FAN_ODD_MAX - $FAN_ODD_MIN) / ($GPU_MAX_TEMP - $GPU_HIGH_TEMP))) | |
| MEM_FAN_STEP=$((($FAN_HDD_MAX - $FAN_HDD_MIN) / ($MEM_MAX_TEMP - $MEM_HIGH_TEMP))) | |
| SSD_FAN_STEP=$((($FAN_HDD_MAX - $FAN_HDD_MIN) / ($SSD_MAX_TEMP - $SSD_HIGH_TEMP))) | |
| PSU_FAN_STEP=$((($FAN_CPU_MAX - $FAN_CPU_MIN) / ($PSU_MAX_TEMP - $PSU_HIGH_TEMP))) | |
| CPU_FAN_STEP=$((($FAN_CPU_MAX - $FAN_CPU_MIN) / ($CPU_MAX_TEMP - $CPU_HIGH_TEMP))) | |
| # Set manual fan mode | |
| echo 1 > "${FAN_ODD_DEVICE}manual" | |
| echo 1 > "${FAN_HDD_DEVICE}manual" | |
| echo 1 > "${FAN_CPU_DEVICE}manual" | |
| # Main loop | |
| while true; do | |
| GPU_TEMP=$(<"${GPU_TEMP_SENSOR}"); GPU_TEMP=$(($GPU_TEMP/1000)) | |
| MEM_TEMP=$(<"${MEM_TEMP_SENSOR}"); MEM_TEMP=$(($MEM_TEMP/1000)) | |
| SSD_TEMP=$(<"${SSD_TEMP_SENSOR}"); SSD_TEMP=$(($SSD_TEMP/1000)) | |
| PSU_TEMP=$(<"${PSU_TEMP_SENSOR}"); PSU_TEMP=$(($PSU_TEMP/1000)) | |
| CPU1_TEMP=$(<"${CPU1_TEMP_SENSOR}"); CPU1_TEMP=$(($CPU1_TEMP/1000)) | |
| CPU2_TEMP=$(<"${CPU2_TEMP_SENSOR}"); CPU2_TEMP=$(($CPU2_TEMP/1000)) | |
| # Work out fan speeds and test for sanity | |
| GPU_FAN=$((($GPU_TEMP - $GPU_HIGH_TEMP) * $GPU_FAN_STEP + $FAN_ODD_MIN)) | |
| if [ "$GPU_FAN" -lt "$FAN_ODD_MIN" ] ; then GPU_FAN=$FAN_ODD_MIN ; fi | |
| if [ "$GPU_FAN" -gt "$FAN_ODD_MAX" ] ; then GPU_FAN=$FAN_ODD_MAX ; fi | |
| MEM_FAN=$((($MEM_TEMP - $MEM_HIGH_TEMP) * $MEM_FAN_STEP + $FAN_HDD_MIN)) | |
| if [ "$MEM_FAN" -lt "$FAN_HDD_MIN" ] ; then MEM_FAN=$FAN_HDD_MIN ; fi | |
| if [ "$MEM_FAN" -gt "$FAN_HDD_MAX" ] ; then MEM_FAN=$FAN_HDD_MAX ; fi | |
| SSD_FAN=$((($SSD_TEMP - $SSD_HIGH_TEMP) * $SSD_FAN_STEP + $FAN_HDD_MIN)) | |
| if [ "$SSD_FAN" -lt "$FAN_HDD_MIN" ] ; then SSD_FAN=$FAN_HDD_MIN ; fi | |
| if [ "$SSD_FAN" -gt "$FAN_HDD_MAX" ] ; then SSD_FAN=$FAN_HDD_MAX ; fi | |
| PSU_FAN=$((($PSU_TEMP - $PSU_HIGH_TEMP) * $PSU_FAN_STEP + $FAN_CPU_MIN)) | |
| if [ "$PSU_FAN" -lt "$FAN_CPU_MIN" ] ; then PSU_FAN=$FAN_CPU_MIN ; fi | |
| if [ "$PSU_FAN" -gt "$FAN_CPU_MAX" ] ; then PSU_FAN=$FAN_CPU_MAX ; fi | |
| CPU1_FAN=$((($CPU1_TEMP - $CPU_HIGH_TEMP) * $CPU_FAN_STEP + $FAN_CPU_MIN)) | |
| if [ "$CPU1_FAN" -lt "$FAN_CPU_MIN" ] ; then CPU1_FAN=$FAN_CPU_MIN ; fi | |
| if [ "$CPU1_FAN" -gt "$FAN_CPU_MAX" ] ; then CPU1_FAN=$FAN_CPU_MAX ; fi | |
| CPU2_FAN=$((($CPU2_TEMP - $CPU_HIGH_TEMP) * $CPU_FAN_STEP + $FAN_CPU_MIN)) | |
| if [ "$CPU2_FAN" -lt "$FAN_CPU_MIN" ] ; then CPU2_FAN=$FAN_CPU_MIN ; fi | |
| if [ "$CPU2_FAN" -gt "$FAN_CPU_MAX" ] ; then CPU2_FAN=$FAN_CPU_MAX ; fi | |
| # Set the fan speeds | |
| ODD_FAN=$GPU_FAN | |
| HDD_FAN=$MEM_FAN | |
| if [ "$SSD_FAN" -gt "$HDD_FAN" ] ; then HDD_FAN=$SSD_FAN ; fi | |
| CPU_FAN=$PSU_FAN | |
| if [ "$CPU1_FAN" -gt "$CPU_FAN" ] ; then CPU_FAN=$CPU1_FAN ; fi | |
| if [ "$CPU2_FAN" -gt "$CPU_FAN" ] ; then CPU_FAN=$CPU2_FAN ; fi | |
| echo $ODD_FAN > "${FAN_ODD_DEVICE}output" | |
| echo $HDD_FAN > "${FAN_HDD_DEVICE}output" | |
| echo $CPU_FAN > "${FAN_CPU_DEVICE}output" | |
| sleep 5 | |
| done | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # macpro-fancontrol.sh — configurable Mac Pro fan controller template | |
| # Requires: an smc CLI tool in PATH. Configure READ/WRITE commands below. | |
| # --- CONFIG: adapt these after we know your SMC keys --- | |
| # Map of sensor keys to threshold (Celsius) and target fan RPM | |
| # Example entries below are placeholders; replace keys after you supply `smc -l` output. | |
| SENSORS=( | |
| "TC0P:60:fan0:2500" # sensor_key:warn_temp_C:fan_id:target_rpm | |
| "TG0D:70:fan1:3000" | |
| ) | |
| # Fan control command placeholders: | |
| # Replace these with the correct read/write commands for your `smc` binary. | |
| SMC_READ() { | |
| # usage: SMC_READ KEY | |
| # Example: sudo smc -k "$1" -r | |
| sudo smc -k "$1" -r 2>/dev/null | |
| } | |
| SMC_WRITE_RPM() { | |
| # usage: SMC_WRITE_RPM FAN_ID RPM | |
| # Example: sudo smc -k "F0Mn" -w 0x0BB8 (if your smc expects hex values) | |
| # This is a placeholder — we'll adapt after you paste your smc output. | |
| echo "WRITE: fan $1 -> $2 rpm (not yet implemented for this smc CLI)" | |
| } | |
| POLL_INTERVAL=10 | |
| # --- helpers --- | |
| get_temp() { | |
| key="$1" | |
| out="$(SMC_READ "$key")" | |
| # Attempt to extract float from output; adapt if your smc prints differently. | |
| echo "$out" | grep -Eo '[0-9]+(\.[0-9]+)?' | head -1 | |
| } | |
| set_fan() { | |
| fan_id="$1" | |
| rpm="$2" | |
| SMC_WRITE_RPM "$fan_id" "$rpm" | |
| } | |
| # --- main loop --- | |
| while true; do | |
| now="$(date +'%Y-%m-%d %H:%M:%S')" | |
| echo "[$now] checking sensors..." | |
| for entry in "${SENSORS[@]}"; do | |
| IFS=':' read -r skey thresh fanid target <<< "$entry" | |
| temp="$(get_temp "$skey")" | |
| if [ -z "$temp" ]; then | |
| echo " $skey: read failed" | |
| continue | |
| fi | |
| temp_int=${temp%.*} | |
| echo " $skey -> ${temp}C (warn ${thresh}C) -> $fanid" | |
| if [ "$temp_int" -ge "$thresh" ]; then | |
| echo " threshold exceeded: setting $fanid -> ${target}rpm" | |
| set_fan "$fanid" "$target" | |
| fi | |
| done | |
| sleep "$POLL_INTERVAL" | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment